开发者

private method `chomp' called for nil:NilClass (NoMethodError)

开发者 https://www.devze.com 2023-03-05 17:00 出处:网络
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:

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 and join is common in similar cases. print does not add a line break while puts 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, use system('clear').
  • You have a method entToLatin, and it should work, but it is a ruby convention to use underscore, like eng_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
0

精彩评论

暂无评论...
验证码 换一张
取 消