私有方法`chomp'调用nil:NilClass(NoMethodError)

时间:2011-05-12 16:22:38

标签: ruby

我试图通过将Java程序转换为Ruby来学习Ruby,但是我一直在想出围绕这段代码的错误:

  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

我一直收到这个错误:

EnglishToPigLatin.rb:14:in `create': private method `chomp' called for nil:NilClass (NoMethodError)
    from EnglishToPigLatin.rb:60

这是第60行附近的区域:

#if __FILE__ == $0

  mg = EnglishToPigLatin.new
  mg.create

#end

基本上我要做的是在仍有输入时,获取输入,将其拆分为单个单词,并通过Pig Latin转换方法运行每个单词。

2 个答案:

答案 0 :(得分:5)

看起来你正试图在你的循环中输入。

尝试

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

否则,当没有输入时,你会尝试获取下一行输入。此外,do声明不需要while 您也无需将@user_input重置为''

由于这只是一个块,你不需要使用实例变量,除非你调用的方法需要它们。

此外,您的条件始终为真。 gets将阻塞,直到获得一行输入。您可以使用loop进行以中断结束的无限循环。

此外,如果您使用STDOUT作为最后一行而不是puts,则无需刷新print

整个事情可能是模块中的脚本或方法。甚至不需要制作实例。如果您这样做,而不是使用mg.create两行,则应定义initialize方法。这用作构造函数,无论你在创建实例时设置的是什么,都应放在那里。

这一切都可以这样做:

loop do
  puts gets.chomp.split(' ').map{ |x| x.engToLatin() }.join(' ')
  puts "EOF to Quit"
end

答案 1 :(得分:2)

马里奥的回答是正确的。但我有以下注意事项。

  • 您仍然可以使用while构造,如下所示。
  • +' '表示您不希望在每个单词后面换行。我改变了那一部分。 mapjoin在类似情况下很常见。在print执行时,puts不会添加换行符。
  • 我不确定您要对STDOUT.flush做什么。如果您想在每次输出前滚动到屏幕顶部,请使用system('clear')
  • 你有一个方法entToLatin,它应该可行,但使用下划线是一种红宝石惯例,如eng_to_latin方法(尽管有一些例外)。

因此,更为红润的方式是:

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

如果您使用的是ruby 1.9.2,则可以缩短map以便:

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