Ruby与Integer.chr和“\ 001”不熟悉的字符串用法

时间:2011-08-03 21:05:05

标签: ruby

最近我在Ruby中偶然发现了这段代码:

@data = 3.chr * 5

导致“\ 003 \ 003 \ 003 \ 003 \ 003”

稍后在代码

flag = @data[2] & 2

用于, 我知道它有点按钮标记的东西。似乎值1,2和3用作状态标志,但是因为ruby 1.9,这是我熟悉的版本,改变了Integer.chr方法,代码不再有效,我真的想知道什么是上。 此外,“\ 00x”逃脱的目的是什么?

感谢您的回答

3 个答案:

答案 0 :(得分:4)

要使代码在Ruby 1.9中运行,请尝试将该行更改为:

flag = @data[2].ord & 2

在Ruby 1.9之前,str[n]将返回0到255之间的整数,但在Ruby 1.9中支持新的unicode,str[n]返回一个字符(长度为1的字符串)。要获取整数而不是字符,可以在字符上调用.ord

&运算符只是C,Ruby和许多其他语言的标准按位AND运算符。

第三个字节(0x03)不是可打印的ASCII字符,因此当您在字符串中有该字节并调用inspect时,ruby将该字节表示为\003。只要确保你理解“\ 003”是一个单字节字符串,而'\ 003'是一个四字节字符串。

在Ruby中,字符串实际上是字节序列。在Ruby 1.9中,还有编码信息,但它们实际上只是一个字节序列。

答案 1 :(得分:1)

" \ 00X" thing是值的八进制表示。

所以,如果我们这样做:

irb(main):001:0> 15.chr
=> "\017"
irb(main):002:0> 16.chr
=> "\020"

请注意我们是如何从17到20的?八。

" \ 003 \ 003 \ 003 \ 003 \ 003"是值3的5个字节然后你可以按位和其他字节,如2或\ 002。

因此2或0010(2)的二进制中的3或0011是2(0010)

1.9问题是因为1.9不使用像1.8这样的ascii。大卫格雷森很好地说明了这一点。

答案 2 :(得分:1)

请注意,ruby 1.9将检查十六进制表示中的不可打印字符:

3.chr  # => "\x03"

更令人困惑的是,有时字符串将以unicode(UTF-8)显示:

"\003" # => "\u0003"  (utf-8)
3.chr.encoding  # => #<Encoding:US-ASCII>
"\003".encoding  # => #<Encoding:UTF-8>
"\003" == 3.chr  # => true (this is strange because the encoding is different)

如果您试图了解这些八进制和十六进制字符串与十进制数字的关系,您可以将它们转换为二进制数:

"\003".unpack('B*')  # same as "\003".ord.to_s(2)
# => ["00000011"]  # the 2 least significant bits are set
2.to_s(2)  # convert to base 2
#=> "10"

表达式3 & 2是按位和二进制数11b和10b,它将产生10b(因为1和1对于最高有效位是1; 1&amp; 0对于最低有效位是0) 。

其他转换:

'%x' % 97  # => '61' hex
0x61  # => 97 decimal from raw hex input
'%o' % 97  # => '141' octal
0141  # => 97 decimal from raw octal input

这是一种速成课程,但你应该谷歌更深入的信息。