Ruby中与chr()相反的方法是什么?

103

在许多编程语言中,都有一对函数chr()ord(),用于数字与字符值之间的转换。在某些语言中,ord()被称为asc()

Ruby拥有Integer#chr函数,非常好用:

>> 65.chr
A

好的,但是如何反过来呢?

"A".each_byte do |byte|
   puts byte
end

输出:

65

这差不多是我想要的。但我真的想避免使用循环 - 我正在寻找一些在声明 const 时足够简短易读的东西。

10个回答

84
如果在1.9中不存在String#ord方法,它将在2.0中存在:
"A".ord #=> 65

33
在 Ruby 1.8 系列及之前的版本中,以下代码均会产生数值 65(ASCII 码):
puts ?A
'A'[0]

在Ruby 1.9中,这种行为已经发生了改变,上述代码都会输出"A"。在Ruby 1.9中正确的写法是:

The behavior has changed in Ruby 1.9, both of the above will produce "A" instead. The correct way to do this in Ruby 1.9 is:

'A'[0].ord

不幸的是,在Ruby 1.8中并不存在ord方法。


很不幸,在Ruby 1.9中,“正确”的方式非常冗长,但至少在搜索“ord”时会更容易找到。感谢您详细的回答。 - RJHunter

13

尝试:

'A'.unpack('c')

1
现在Ruby 1.9已经改变了'A'[0]的含义,这是更具可移植性的方法。 - AShelly

10

我想赞同dylanfm和AShelley的评论,并补充[0]:

'A'.unpack('C')[0]

unpack调用返回一个包含单个整数的数组,这并不总是被接受为整数所需的内容:

$ ruby -e 'printf("0x%02X\n", "A".unpack("C"))'
-e:1:in `printf': can't convert Array into Integer (TypeError)
    from -e:1
$ ruby -e 'printf("0x%02X\n", "A".unpack("C")[0])'
0x41
$ 

我正在尝试编写适用于Ruby 1.8.1、1.8.7和1.9.2的代码。

编辑以使用大写字母C传递给unpack,因为在我的平台上运行时,C的char是有符号的,而unpack("c")给我-1,而ord()给我255。


5

在按照RFCs准备纯Ruby版本的Stringprep时,我遇到了这个问题。

请注意,chr在[0,255]之外会失败,因此请使用1.9.x - 2.1.x可移植的替代方法:

[22] pry(main)> "\u0221".ord.chr
RangeError: 545 out of char range
from (pry):2:in 'chr'
[23] pry(main)> x = "\u0221".unpack('U')[0]
=> 545
[24] pry(main)> [x].pack('U')
=> "ȡ"
[25] pry(main)>

2
谢谢,这似乎是唯一一个正确给出Unicode中char及其反函数的答案。 - Munyari
如果有人路过,请注意这里的重要上下文在这里在这里 - New Alexandria

3
此外,如果您在字符串中有该字符并且想要解码它而不使用循环:
puts 'Az'[0]
=> 65
puts 'Az'[1]
=> 122

2
如果您不介意从数组中提取值,可以使用"A".bytes

2
你可以拥有这些:
65.chr.ord
'a'.ord.chr

2

你觉得怎么样?

puts ?A


0

我正在编写适用于1.8.6和1.9.3的代码,但是我无法让这些解决方案在两个环境中都起作用 :(

然而,我找到了另一个解决方案: http://smajnr.net/2009/12/ruby-1-8-nomethoderror-undefined-method-ord-for-string.html

那对我也没用,但我为我的使用进行了调整:

unless "".respond_to?(:ord)
  class Fixnum
    def ord
      return self
    end
  end
end

完成这个步骤后,以下内容将在两个环境中都能正常工作。

'A'[0].ord


当user18096编写他们的答案时,"A".unpack("C")[0],那是针对Ruby 1.8.1、Ruby 1.8.7和Ruby 1.9.2。在你的环境中它失败了吗?出现了什么样的错误? - RJHunter
嗨RJHunter,我正在尝试将字符串中的特定字符转换为其数值。以下代码适用于1.9.3但不适用于1.8.6。 self.status = tagAccountString[4].unpack('C')[0] 在1.8.6中我得到了 Exception undefined method 'unpack' for 0:Fixnum processing main buffered tag data - exit 以下代码(使用我的解决方案)在两个环境中都有效。 self.status = tagAccountString[4].ord 任何建议(例如更好的解决方案)都非常欢迎。 - hantscolin
tagAccountString[4] 在新版本的 Ruby 中返回一个字符串,但在 Ruby 1.8 中返回一个 Fixnum。这就是为什么你看到了错误 undefined method unpack for 0:Fixnum。你可以使用 status = tagAccountString[4,1].unpack('C')[0] 或者 status, = tagAccountString.unpack('xxxxC'),如果你总是想忽略前四个字符并转换下一个字符。 - RJHunter
感谢RJHunter的解释和替代方案。然而,由于“我的”解决方案更易读且更可重用,我将坚持使用它(除非有充分的理由不这样做?) - hantscolin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接