Comment analyser un nombre à partir d’une chaîne pouvant avoir un zéro non significatif ?

StackOverflow https://stackoverflow.com/questions/146668

  •  02-07-2019
  •  | 
  •  

Question

En Ruby, j'analyse une date au format suivant :24092008.Je souhaite convertir chaque section (année, mois, date) en un nombre.

Je les ai divisés à l'aide d'une expression régulière qui produit trois chaînes que je transmets au constructeur Integer.

  date =~ /^([\d]{2})([\d]{2})([\d]{4})/
  year = Integer($3)
  month = Integer($2)
  day = Integer($1)

Lorsqu'il atteint la ligne du mois, il plante comme suit :

`Integer': invalid value for Integer: "09" (ArgumentError)

Il m'a fallu un certain temps pour réaliser qu'il interprète le zéro non significatif comme Octal et que 09 n'est pas un nombre Octal valide (cela fonctionne bien avec "07").

Existe-t-il une solution élégante à ce problème ou dois-je simplement tester les nombres inférieurs à 10 et supprimer d'abord le zéro ?

Merci.

Était-ce utile?

La solution

Je ne connais pas bien les expressions rationnelles, alors pardonnez-moi si cette réponse est erronée. Je suppose que 3 $, 2 $ et 1 $ sont des chaînes. Voici ce que j'ai fait à la CISR pour reproduire le problème:

irb(main):003:0> Integer("04")
=> 4
irb(main):004:0> Integer("09")
ArgumentError: invalid value for Integer: "09"
    from (irb):4:in `Integer'
    from (irb):4
    from :0

Mais il semble que .to_i n'a pas les mêmes problèmes:

irb(main):005:0> "04".to_i
=> 4
irb(main):006:0> "09".to_i
=> 9

Autres conseils

Spécifiez la base 10

Dites explicitement à Ruby que vous souhaitez interpréter la chaîne comme un nombre de base 10.

Integer("09", 10) # => 9

C'est meilleur que .to_i si vous voulez être strict .

"123abc".to_i # => 123
Integer("123abc", 10) # => ArgumentError

Comment j'ai compris cela

Dans irb, method(:Integer) renvoie #<Method: Object(Kernel)#Integer>. Cela m'a dit que Kernel est propriétaire de cette méthode et j'ai consulté la documentation sur le noyau. La signature de la méthode indique qu'il faut base comme second argument.

Peut-être (0([\d])|([1-9][\d])) au lieu de ([\d]{2})Vous devrez peut-être utiliser 2 $, 4 $ et 5 $ au lieu de 1 $, 2 $, 3 $.

Ou si votre expression rationnelle prend en charge (?:...) puis utilise (?:0([\d])|([1-9][\d]))

Puisque Ruby prend son expression rationnelle de Perl, cette dernière version devrait fonctionner.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top