【问题标题】:private method `chomp' called for nil:NilClass (NoMethodError)私有方法 `chomp' 调用 nil:NilClass (NoMethodError)
【发布时间】:2011-05-12 16:22:38
【问题描述】:

我正在尝试通过将 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 转换方法运行每个单词。

【问题讨论】:

    标签: ruby


    【解决方案1】:

    您似乎正在尝试在循环中获取输入。

    试试

    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 用于以中断结束的无限循环。

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

    整个事情可以是一个脚本或模块中的一个方法。甚至不需要创建实例。如果你这样做了,你应该定义一个initialize 方法,而不是在mg.create 中使用两行。然后将其用作构造函数,并且您在创建实例时设置的任何内容都应该放在那里。

    都可以这样完成:

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

    【讨论】:

    • 这修复了我当前的错误,但后来给我留下了错误。我已经用更多信息更新了我原来的帖子。
    • /media/Storage/Documents/Ruby/EnglishToPigLatin.rb:25: 未定义方法 string' for "test":String (NoMethodError) from /media/Storage/Documents/Ruby/EnglishToPigLatin.rb:23:in loop' from /media/Storage/Documents/Ruby/EnglishToPigLatin.rb:23 其中 23 是 loop do
    • 哦,是的。修正了我的答案。你想要.to_s,而不是.string。虽然已经是字符串了。
    • 好的,已经解决了。上述错误的一部分也是由于我不小心注释掉了部分原始代码。
    • 原始代码是否有user_input = gets.chomp!(如您的答案)或user_input = gets.chomp
    【解决方案2】:

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

    • 您仍然可以使用while 结构,如下所示。
    • +' ' 表示您不想在每个单词后换行。我改变了那部分。 mapjoin 在类似情况下很常见。 print 不会添加换行符,而 puts 会添加。
    • 我不确定你想用STDOUT.flush 做什么。如果您想在每次输出之前滚动到屏幕顶部,请使用system('clear')
    • 您有一个方法 entToLatin,它应该可以工作,但使用下划线是 ruby​​ 的惯例,例如 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
    

    【讨论】:

    • 这是一个很好的观点。 puts 添加了一个新行,所以@GeoffB 如果他试图在一行上打印一个句子,应该避免使用它。
    • @Mario 是的。 OP 需要区分putsprint。感谢您的评论。
    • 那么,puts 类似于 java 的 S.O.println,而print 类似于 java 的 S.O.print?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多