为什么这个ruby使用\ u001表示1以及如何更改?

时间:2014-10-16 12:27:48

标签: ruby fizzbuzz

我已经写过经典的fizzbuzz代码。

规范:

describe "can determine fizzbuxx output for" do
  it "3" do
    expect(Fizzbuzz.nums(3)).to eq "123fizz"
  end 
end

代码:

class Fizzbuzz
  def self.nums(n)
    result=""
    (1..n).each do |inner|
      puts "inner #{inner}"
      result << inner
      if (inner % 3)==0
        result << 'fizz'
      end
      if (inner % 5)==0
        result << 'buzz'
      end
    end
    result
  end
end

为什么我会\u001而不是1

Failures:

1) can determine fizzbuxx output for 3
 Failure/Error: expect(Fizzbuzz.nums(3)).to eq "123fizz"

   expected: "123fizz"
        got: "\u0001\u0002\u0003fizz"

   (compared using ==)
 # ./fizzbuzz_spec.rb:5:in `block (2 levels) in <top (required)>'

这是某种utf-8问题吗?

3 个答案:

答案 0 :(得分:3)

这是String#<<方法的预期行为。来自Ruby documentation

  

将给定对象连接到str。如果对象是Integer,则将其视为代码点,并在连接之前转换为字符。

您必须在追加之前将整数显式转换为字符串:

'' << 1 # => "\u0001"
'' << 1.to_s => "1"

答案 1 :(得分:3)

在Ruby for string concatenation: <<中,如果对象是Integer,则将其视为代码点,并在连接之前转换为字符。而且由于Ruby 1.9的默认编码是UTF-8。强制使用UTF-8编码码点:

1.chr(Encoding::UTF_8)
# => "\u0001"

所以,当你这样做时:

"" << 1

Ruby实际上将1视为代码点并尝试将其转换为使用UTF-8编码的字符串,实际上会改为:

"" << 1.chr(Encoding::UTF_8)
#=> "\u0001"

所以,解决你的问题。您可以通过将代码更改为:

将Fixnum显式转换为String
result << inner.to_s

或使用字符串插值:

result << "#{inner}"

答案 2 :(得分:0)

对于小数字,它们的类型是FixNum [保持整数值,可以用本机机器字(减1位)表示。 ]

result << inner

将其显式转换为String,您将获得所需的结果。

result << inner.to_s