2008-11-21 7 views
84

Dans plusieurs langues, il existe une paire de fonctions, chr() et ord(), qui convertissent entre les nombres et les valeurs de caractères. Dans certaines langues, ord() est appelé asc().Quel est le contraire de chr() dans Ruby?

Ruby a Integer#chr, qui fonctionne très bien:

>> 65.chr 
A 

assez juste. Mais comment allez-vous dans l'autre sens?

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

impressions:

65 

et c'est assez proche de ce que je veux. Mais je préfère vraiment éviter une boucle - je cherche quelque chose de suffisamment court pour être lisible lors de la déclaration const.

Répondre

68

Si String # ord n'existait pas dans 1.9, il le fait dans 2.0:

"A".ord #=> 65 
+0

Fonctionne également sur 2.1 – Kostas

2

Que diriez-vous

met

13

Essayez:

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

Maintenant que Ruby 1.9 a changé la signification de 'A' [0], c'est la méthode la plus portable. – AShelly

3

De plus, si vous avez le caractère dans une chaîne et que vous voulez décoder sans une boucle:

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

Dans Ruby jusqu'à et y compris ce qui suit produira deux, série 65 1,8 (pour ASCII):

puts ?A 
'A'[0] 

Le comportement a changé dans Ruby 1.9, tous deux du produira au-dessus de « A » à la place. La bonne façon de le faire en Ruby 1.9 est:

'A'[0].ord 

Malheureusement, la méthode ord n'existe pas dans Ruby 1.8.

+0

Il est regrettable que la méthode "correcte" dans Ruby 1.9 soit si longue, mais au moins cela apparaîtra plus facilement dans les recherches de "ord". Merci pour votre réponse très détaillée. – RJHunter

+2

'A' [0] .ord mots en rubis 1.8.7 - et merci pour la réponse. –

10

Je voudrais +1 dylanfm et le commentaire de AShelly mais ajoute [0]:

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

L'appel Déballez retourne un tableau contenant un seul entier, ce qui est pas toujours acceptée si un entier est recherché:

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

J'essaye d'écrire du code qui fonctionne sur Ruby 1.8.1, 1.8.7 et 1.9.2.

Édité pour passer C pour décompresser en majuscule, car unpack ("c") me donne -1 où ord() me donne 255 (malgré le fait de fonctionner sur une plate-forme où le caractère de C est signé).

1

Vous pouvez avoir ces:

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

Juste suis tombé sur ce tout en mettant ensemble une version de Ruby pur Stringprep via RFCs.

Prenez garde que chr échoue en dehors de [0255], utilisez plutôt 1.9.x - remplacement portables 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)> 
+0

Merci, cela semble être la seule réponse qui donne 'char' et son inverse dans le cas d'unicode correctement – Munyari

2

Si vous ne me dérange pas tirer les valeurs hors d'un tableau, vous pouvez utiliser "A".bytes

0

J'écrire du code pour 1.8.6 et 1.9.3 et je ne pouvais pas obtenir l'une de ces solutions pour travailler dans les deux environnements :(

Cependant, je suis tombé sur une autre solution: http://smajnr.net/2009/12/ruby-1-8-nomethoderror-undefined-method-ord-for-string.html

Cela n'a pas fonctionné pour moi non plus, mais je l'ai adapté pour mon utilisation:

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

Après avoir fait cela, alors ce qui suit fonctionnera dans les deux environnements

'A'[0].ord

+0

Quand user18096 a écrit sa réponse,' "A" .unpack ("C") [0 ] ', qui ciblait Ruby 1.8.1, Ruby 1.8.7 et Ruby 1.9.2. Est-ce qu'il échoue dans votre environnement? Quel genre d'échec? – RJHunter

+0

Salut RJHunter, j'essaie de convertir un caractère spécifique dans une chaîne à sa valeur numérique. Le code suivant fonctionne en 1.9.3 mais pas en 1.8.6. 'self.status = tagAccountString [4] .unpack ('C') [0]' Dans 1.8.6 j'obtiens 'Exception méthode non définie' décompresser 'pour 0: Fixnum traitement des données de balises tampons - sortie' le code suivant fonctionne (avec la solution que je propose) dans les deux environnements 'self.status = tagAccountString [4] .ord' Tout conseil (par exemple une meilleure solution) est le bienvenu – hantscolin

+0

' tagAccountString [4] 'renvoie une chaîne dans la version plus récente Rubis mais utilisé pour renvoyer un Fixnum en Ruby 1.8. C'est pourquoi vous avez vu l'erreur, 'méthode non définie décompresser pour 0: Fixnum'. Vous pouvez utiliser 'status = tagAccountString [4,1] .unpack ('C') [0]' ou même 'status, = tagAccountString.unpack ('xxxxC')' si vous voulez toujours ignorer quatre caractères et convertir le suivant un. – RJHunter

Questions connexes