2008-11-21 11 views
84

W wielu językach dostępne są dwie funkcje: chr() i ord(), które służą do konwersji liczb i wartości znaków. W niektórych językach ord() nazywa się asc().Co jest przeciwieństwem chr() w Ruby?

Ruby ma Integer#chr, który działa świetnie:

>> 65.chr 
A 

Słusznie. Ale jak idziesz w drugą stronę?

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

drukuje:

65 

i to całkiem blisko tego, co chcę. Ale wolałbym raczej uniknąć pętli - szukam czegoś wystarczająco krótkiego, aby można je było odczytać podczas deklarowania const.

Odpowiedz

68

Jeśli w wierszu 1.9 nie istniał ciąg # ord, ma on wartość 2.0:

"A".ord #=> 65 
+0

Działa również na 2.1 – Kostas

13

Spróbuj:?

'A'.unpack('c') 
+1

Teraz, gdy Ruby 1.9 zmieniło znaczenie "A" [0], jest to bardziej przenośna metoda. – AShelly

3

Dodatkowo, jeśli masz char w ciąg i chcesz dekodować go bez pętli:

puts 'Az'[0] 
=> 65 
puts 'Az'[1] 
=> 122 
33

Ruby włącznie serii 1.8, dodaje się zarówno produkcji 65 (ASCII)

puts ?A 
'A'[0] 

Zachowanie się zmieniło w Ruby 1.9 oba powyższe będzie wytwarzać zamiast „A”. Poprawny sposób to zrobić w Ruby 1.9 jest:

'A'[0].ord 

Niestety, metoda ord nie istnieje w Ruby 1.8.

+0

To niefortunne, że "poprawna" metoda w Rubim 1.9 jest tak długa, ale przynajmniej będzie łatwiejsza w wyszukiwaniu "ord". Dzięki za bardzo szczegółową odpowiedź. – RJHunter

+2

"A" [0] .ord słowa w rubinach 1.8.7 - i dziękuję za odpowiedź. –

10

Chciałbym +1 dylanfm i komentarz AShelly, ale dodać [0]:

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

rozpakować wywołanie zwraca tablicę zawierającą jedną liczbę całkowitą, która nie zawsze jest akceptowana gdzie liczbą całkowitą jest poszukiwany:

 
$ 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 
$ 

Próbuję napisać kod, który działa na Ruby 1.8.1, 1.8.7 i 1.9.2.

Edytowany w celu przekazania C do rozpakowania wielkimi literami, ponieważ rozpakowanie ("c") daje mi -1, gdzie ord() daje mi 255 (pomimo uruchamiania na platformie, na której podpis C jest char).

1

Możesz mieć te:

65.chr.ord 
'a'.ord.chr 
3

Właśnie natknąłem się na to podczas układania czystą wersję Ruby z Stringprep poprzez RFC.

Pamiętaj, że chr nie na zewnątrz [0255], zamiast używać 1.9.x - 2.1.xi przenośne zamienników:

[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)> 
+0

Dziękuję, to wydaje się być jedyną odpowiedzią, która daje 'char' i jej odwrotność w przypadku poprawnego unicode – Munyari

2

Jeśli nie przeszkadza wyciągając wartości z tablicy, można użyć "A".bytes

0

Piszę kodu dla 1.8.6 i 1.9.3 i nie mogłem dostać żadnej z tych rozwiązań do pracy w obu środowiskach :(

jednak natknąłem innego rozwiązania: http://smajnr.net/2009/12/ruby-1-8-nomethoderror-undefined-method-ord-for-string.html

To nie dla mnie też, ale przystosowane dla mojego użytku:

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

zrobiwszy, wtedy dodaje będą pracować w obu środowiskach

'A'[0].ord

+0

Gdy user18096 napisał odpowiedź,' 'A" .unpack ("C") [0 ] ', który był ukierunkowany na Ruby 1.8.1, Ruby 1.8.7 i Ruby 1.9.2. Czy to nie działa w twoim środowisku? Jakiego rodzaju niepowodzenia? – RJHunter

+0

Witaj RJHunter, Próbuję przekonwertować określony znak w ciągu na jego wartość liczbową. Poniższy kod działa w wersji 1.9.3, ale nie 1.8.6. 'self.status = tagAccountString [4] .unpack (" C ") [0]' W wersji 1.8.6 otrzymuję 'Wyjątek niezdefiniowana metoda' unpack 'dla 0: Fixnum przetwarzające główne buforowane dane znaczników - exit' The następujący kod działa (z moim proponowanym rozwiązaniem) w obu środowiskach 'self.status = tagAccountString [4] .ord' Każda rada (np. lepsze rozwiązanie) jest więcej niż mile widziana – hantscolin

+0

' tagAccountString [4] 'zwraca ciąg w nowszej wersji Rubiny, ale używane do zwracania Fixnum w Rubim 1.8. Właśnie dlatego zobaczyłeś błąd, 'nieokreślona metoda rozpakuj dla 0: Fixnum'. Możesz użyć 'status = tagAccountString [4,1] .unpack ('C') [0]' lub nawet 'status, = tagAccountString.unpack ('xxxxC')' jeśli zawsze chcesz zignorować cztery znaki i przekonwertować następny jeden. – RJHunter

Powiązane problemy