简体   繁体   中英

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 been 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM