private method `chomp' called for nil:NilClass (NoMethodError)
I am attempting to learn Ruby by converting a Java program to Ruby, but I've been coming up with an error surrounding this block of code:
def create
@user_input = String.new()
# @word_arr = Array.new
print "Enter the text to be converted to pig latin, EOF to quit: "
while gets do
STDOUT.flush
@user_input = gets.chomp
@word_arr = @user_input.string.split(' ')
@word_arr.each { |x| puts x.engToLatin() + ' '}
print "EOF to Quit"
@user_input = ""
end
end
I've be开发者_开发问答en getting this error:
EnglishToPigLatin.rb:14:in `create': private method `chomp' called for nil:NilClass (NoMethodError)
from EnglishToPigLatin.rb:60
This is the area around line 60:
#if __FILE__ == $0
mg = EnglishToPigLatin.new
mg.create
#end
Essentially what I am trying to do is while there is still input, get that input, split it up into individual words, and run each word through a Pig Latin conversion method.
It looks like you're trying to get input inside of your loop.
Try
loop do
user_input = gets.chomp!
word_arr = user_input.to_s.split(' ')
word_arr.each { |x| puts x.engToLatin() + ' '}
puts "EOF to Quit"
end
Otherwise you're trying to get the next line of input when there isn't one. Additionally, do
isn't necessary for a while
statement.
You also don't need to reset @user_input
to ''
.
And since this is all in a block, you don't need to use instance variables, unless the methods you call need them.
Also your conditional is always true. gets
will block until it gets a line of input. You can use loop
for an infinite loop that ends on an interrupt.
Also, you needn't flush STDOUT
if you use a puts
for the last line there instead of a print
.
The whole thing could be a script or a method in a module. An instance doesn't even need to be made. And if you do, instead of using two lines with your mg.create
, you should define an initialize
method. This is used as a constructor then, and whatever you set when you create an instance should be put there.
It can all be done like this:
loop do
puts gets.chomp.split(' ').map{ |x| x.engToLatin() }.join(' ')
puts "EOF to Quit"
end
Mario's answer is right. But I have the following notes.
- You can still use the
while
construction as below. +' '
implies that you don't want line breaks after each word. I changed that part.map
andjoin
is common in similar cases.print
does not add a line break whileputs
does.- I am not sure what you are trying to do with
STDOUT.flush
. If you wanted to scroll to the top of the screen before each output, usesystem('clear')
. - You have a method
entToLatin
, and it should work, but it is a ruby convention to use underscore, likeeng_to_latin
for methods (although there are a few exceptions).
So a more rubyish way would be:
def create
print "Enter the text to be converted to pig latin, EOF to quit: "
while input = gets.strip and input != 'EOF'
system('clear')
puts input.split(/\s+/).map{|x| x.engToLatin}.join(' ')
puts "EOP to Quit"
end
end
And if you are using ruby 1.9.2, you can shorten map
so that:
def create
print "Enter the text to be converted to pig latin, EOF to quit: "
while input = gets.strip and input != 'EOF'
system('clear')
puts input.split(/\s+/).map(:engToLatin).join(' ')
puts "EOP to Quit"
end
end
精彩评论