2014-10-16 49 views
1

我写了经典的fizzbuzz代码。为什么这个红宝石使用 u001 for 1以及如何更改?

该规范:

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问题?

+0

可能与您用事实做''<<用'Fixnum'。将其更改为'result << inner.to_s'将产生所需的结果。我相信有人可以挖掘出确切的行为并提供更好的解释。 – 2014-10-16 12:43:08

+0

是的,工作。作为回答发布,我会接受。 thx – 2014-10-16 12:44:59

+1

从['String#<<'](http://www.ruby-doc.org/core-2.1.3/String.html#method-i-3C-3C):*“将给定对象连接到str。如果对象是一个Integer,它被认为是一个代码点,并在连接之前转换为一个字符。“* – Stefan 2014-10-16 12:46:08

回答

3

在Ruby中的字符串concatenation: <<,如果对象是一个整数,它被认为是一个码点,并转换为连接前的字符。由于Ruby 1.9的默认编码是UTF-8。该码点被迫使用UTF-8编码:

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

所以,当你这样做:

"" << 1 

红宝石实际上考虑1作为一个码点,并尝试将其与转换为字符串UTF-8编码,并且实际上会这样做:

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

所以,要解决你的问题。你可以明确地转换到长整数字符串通过改变代码:

​​

或字符串插值:

result << "#{inner}" 
0

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

result << inner 

明确地将其转换为字符串,你会得到你想要的结果。

​​
3

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

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

你必须为整数显式地转换为字符串追加前:

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