7
votes

Problème avec la conversion de chaîne en nombre (strtod)

J'utilise la fonction StrtOD () pour extraire une variable d'environnement en tant que chaîne, puis la modifiant pour doubler à l'aide de StrTOD:

enter code here
 char strEnv[32];
 strncpy(strEnv, getenv("LT_LEAK_START"), 31);
 // How to make sure before parsing that env LT_LEAK_START is indeed a number?
 double d = strtod(strEnv, NULL);


1 commentaires

Vous faites simplement cela en essayant de le convertir en double


6 Réponses :


0
votes

Ce second argument à strtod , que vous avez défini sur null peut être un pointeur à pointer-ponter-to-caractère; Le pointeur-à-char qui indique qu'il sera configuré sur le caractère après la dernière chose strtod géré à analyser. Si c'est la fin de la corde, ou du moins, il n'y a rien de côté qu'après cela, mais avec espace, alors ce que vous aviez été un nombre. Sinon, c'était autre chose.


0 commentaires

16
votes

Le 2e argument de la fonction strtod code> est utile. XXX PRE>


Edition: Exemples ajoutés P>

Le Strtod code> fonction essaie de convertir la partie initiale de la 1ère argument en un double et s'arrête soit lorsqu'il n'y a plus de caractères, ni un caractère qui ne peut pas être utilisé pour faire un double. P>

input         result
----------    ----------------------------
"42foo"       will return 42
              and leave err pointing to the "foo" (*err == 'f')

"     4.5"    will return 4.5
              and leave err pointing to the empty string (*err == 0)

"42         " will return 42
              and leave `err` pointing to the spaces (*err == ' ')


7 commentaires

@PMG: Merci une tonne. Mais je ne suis pas exactement capable de comprendre, qu'est-ce que vous essayez exactement de faire par erreur?


@PMG: Donc, séparément, allons-nous vérifier tous les caractères spéciaux, etc., Isalpha, comme ça?


@PMG: Merci beaucoup pour les exemples. Alors pourquoi vérifier les espaces? Ne pouvons-nous pas vérifier directement pour (* err == 0) ?


L'entrée "4 2" retournera 4 et laissez foo pointant vers "2" . Je pense que c'est un nombre non valide, il suffit de rechercher 1 espace dans * ERR ne suffit pas.


@PMG: Merci, votre est la meilleure explication. Beaucoup d'autres étaient également utiles.


@PMG Cependant, je ne suis toujours pas d'accord avec votre réponse. Si vous avez "foo", * err! = 0` et Isspace ((non signé) * err) == true


@Ugo: vous êtes correct. Mon code ci-dessus est incomplet. Il ne valident pas correctement pour "FOO" ou "" (chaîne vide). Il ne s'agissait que d'un exemple d'utilisation de la 2e argument à strtod () .



0
votes

Je ne sais pas grand chose à propos de cette langue, mais je sais que Strtod () retournera 0,0 si l'entrée est fausse. Peut-être que vous pourriez utiliser une expression régulière pour valider la chaîne d'entrée est un nombre.


0 commentaires

3
votes

homme strtod code>: Si aucune conversion n'est effectuée, zéro est renvoyé et la valeur de NPTR est stockée à l'emplacement référencé par ENDPTR.

char * endptr;
double d = strtod(strEnv, &endptr);
if (strEnv == endptr)
   /* invalid number */
else
   ...


4 commentaires

Vous n'avez pas fait de chèques pour des caractères spéciaux?


@ KingsMasher1 S'il y a un caractère spécial. Ce n'est pas un nombre valide de toute façon. Donc, la conversion échoue et endptr est réglée sur Strenv.


Votre réponse est trompeuse: il peut y avoir des cas où strenv! = Endptr et le numéro était valide, par exemple "42" (espace à la fin)


@pgm En fait, vous avez toujours strenv! = endptr si le numéro est valide.



1
votes
  • Tout d'abord, vérifiez la valeur de retour de getenv - S'il s'agit de NULL, cette variable d'environnement n'existe pas.
  • Deuxièmement, si la valeur de retour de getenv n'est pas null, vous avez la valeur, en tant que chaîne.
  • troisième, ne définissez pas le paramètre char * ** endptr de strtod à NULL, mais utilisez-le pour vérifier la validité de la valeur convertie, vérifiez également < Code> 0.0 .

0 commentaires

2
votes

Sûrement, vous pourriez faire pire que de simplement lire la page d'homme pour Strtod () et agir à ce sujet. Par exemple. Sur mon système Linux, il est indiqué:

RETURN VALUE
       These functions return the converted value, if any.

       If  endptr  is  not  NULL,  a pointer to the character after the last character used in the conversion is stored in the location referenced by
       endptr.

       If no conversion is performed, zero is returned and the value of nptr is stored in the location referenced by endptr.

       If the correct value would cause overflow, plus or minus HUGE_VAL (HUGE_VALF, HUGE_VALL) is returned (according to the sign of the value), and
       ERANGE is stored in errno.  If the correct value would cause underflow, zero is returned and ERANGE is stored in errno.


4 commentaires

Cela ne vous dit pas tout ce que vous devez savoir du tout si vous voulez savoir si la chaîne est valide. Le retour de 0,0 sur erreur est fin, sauf si 0.0 est une valeur de point flottante valide!


@Jonathanwood: Bien sûr. Lisez la page de l'homme plus attentivement!


@Jonathanwood: Il existe de nombreux aspects de C et de la bibliothèque standard C qui peut être considérée comme imparfaite, mais cette fonction n'est pas particulièrement importante sur la liste. Quant à votre question, il est juste là dans la partie que j'ai cité: "Si aucune conversion n'est effectuée, zéro est renvoyé et la valeur de la NPTR est stockée à l'emplacement référencé par ENDPTR."


@Jonathanwood: quant à ce qu'est une "page homme", le premier moteur de recherche est "A href="htttps://fr.wikipedia.org/wiki/man_page" Rel="nofollow NOREFERRER "> EN.Wikipedia.org / wiki / man_page , ce qui l'explique bien. (Notez également que la question est marquée "Linux", de sorte que les systèmes non UNIX pourraient ne pas avoir que les pages de l'homme ne sont pas particulièrement pertinentes ici).