0

我正在尝试“99 瓶”计划。我试图简化它,但我得到“字符串不能被强制转换为 Fixnum”:

num_at_start = 99
num_now = num_at_start         
bobo = " bottles of beer on the wall"
bob = " bottles of beer!"
while num_now > 2
  puts num_now.to_s + bobo.to_s    
  puts num_now.to_s + bob.to_s
  puts num_at_start.to_i - 1 + bobo.to_s
  gets
end
4

2 回答 2

2

问题在这里:

puts num_at_start.to_i - 1 + bobo.to_s

当 args 从左到右进入解释器时,Ruby 建议结果表达式的类型。在这里,您尝试将两个整数相加,使结果为整数。Fixnum#+需要实例 ofFixnum作为操作数,但是bobo.to_s, 即String, 来了。

你应该在这里使用就地评估:

puts "#{num_at_start - 1}#{bobo}"

整个while循环实际上应该写成:

while num_now > 2
  puts "#{num_now}#{bobo}"

  puts "#{num_now}#{bob}"
  puts "#{num_at_start - 1}#{bobo}"
  gets
end

顺便说一句,还有另一个问题:无限循环;但是在您获得现在可以工作的代码后,由您来修复此错误。

于 2013-12-24T05:08:09.350 回答
0

这是我编写代码的方式:

BOBO = '%d bottles of beer on the wall'
BOB = '%d bottles of beer!'

num_at_start = 2
while num_at_start > 0
  bobo_str ||= BOBO % num_at_start
  puts bobo_str
  puts BOB % num_at_start
  puts 'Take one down and pass it around'
  num_at_start -= 1

  bobo_str = BOBO % num_at_start
  puts bobo_str
  puts
end

哪个输出:

# >> 2 bottles of beer on the wall
# >> 2 bottles of beer!
# >> Take one down and pass it around
# >> 1 bottles of beer on the wall
# >> 
# >> 1 bottles of beer on the wall
# >> 1 bottles of beer!
# >> Take one down and pass it around
# >> 0 bottles of beer on the wall
# >> 

我做了一些不同的事情:

  • BOBO现在BOB是字符串格式。有关说明,请参阅String#%Kernel#sprintf文档。
  • 这样做没有意义num_now = num_at_start。只需与num_at_start.
  • 循环测试需要在值大于零时触发,因此编写条件来反映这一点。否则会混淆您和以后处理您的代码的任何其他人。
  • bobo_str ||= BOBO % num_at_startbobo_str如果尚未设置,则它是一种简单的初始化方式。||=基本上是“分配,除非它被设置”。

while我建议不要使用循环,而是使用 Ruby 的downto.

2.downto(1) do |num_at_start|
  bobo_str ||= BOBO % num_at_start
  puts bobo_str
  puts BOB % num_at_start
  puts 'Take one down and pass it around'

  bobo_str = BOBO % (num_at_start - 1)
  puts bobo_str
  puts
end
于 2013-12-24T06:00:01.210 回答