Détection de l’échec de strtol

Comment puis-je détecter si strtol () n’a pas converti un nombre? Je l’ai testé sur le cas simple suivant et il a généré 0. La question évidente est maintenant de savoir comment faire la différence entre une non-conversion et la conversion de 0.

long int li1; li1 = strtol("some ssortingng with no numbers",NULL,10); printf("li1: %ld\n",li1); **** li1: 0 

La déclaration de strtol dans stdio.h est la suivante:

 long int strtol(const char *nptr, char **endptr, int base); 

strtol fournit un schéma de vérification d’erreur et de validation robuste qui vous permet de déterminer si la valeur renvoyée est valid ou invalid . Vous avez essentiellement 3 outils principaux à votre disposition. (1) la valeur renvoyée, (2) la valeur errno est définie sur par l’appel et (3) les adresses et le contenu de nptr et endptr fournis à endptr et définis par celle- strtol . (Voir man 3 strtol pour plus de détails – l’exemple de la page de man fournit également un ensemble de conditions plus courtes à vérifier, mais elles ont été développées ci-dessous pour des explications).

Dans votre cas, vous demandez une valeur de retour de 0 et déterminez si elle est valide. Comme vous l’avez vu, une valeur 0 renvoyée par strtol ne signifie pas que le nombre lu était 0 ou que 0 est valide. Pour déterminer si 0 est valide, vous devez également regarder la valeur que errno été définie pendant l’appel (le cas échéant). Plus précisément, si errno != 0 et que la valeur renvoyée par strtol est 0 , la valeur renvoyée par strtol est INVALID . (cette condition représentera soit invalid base , un overflow supérieur ou un overflow invalid base , avec errno égal à EINVAL ou ERANGE ).

Il existe une deuxième condition qui peut amener strtol renvoyer un INVALID 0 . Le cas où aucun chiffre n’a été lu dans l’entrée. Lorsque cela se produit, strtol définit la valeur de endptr == nptr . Par conséquent, vous devez également vérifier si les valeurs du pointeur sont égales avant de conclure qu’une valeur 0 été entrée. (un 0 VALIDE peut être entré avec plusieurs 0's dans la chaîne)

Vous strtol dessous un exemple des différentes conditions d’erreur à vérifier lors de l’évaluation du retour de strtol ainsi que de plusieurs conditions de test:

 #include  #include  #include  #include  int main (int argc, char **argv) { if (argc < 2) { fprintf (stderr, "\n Error: insufficient input. Usage: %s int [int (base)]\n\n", argv[0]); return 1; } const char *nptr = argv[1]; /* string to read */ char *endptr = NULL; /* pointer to additional chars */ int base = (argc > 2) ? atoi (argv[2]) : 10; /* numeric base (default 10) */ long number = 0; /* variable holding return */ /* reset errno to 0 before call */ errno = 0; /* call to strtol assigning return to number */ number = strtol (nptr, &endptr, base ); /* output original ssortingng of characters considered */ printf ("\n ssortingng : %s\n base : %d\n endptr : %s\n\n", nptr, base, endptr); /* test return to number and errno values */ if (nptr == endptr) printf (" number : %lu invalid (no digits found, 0 returned)\n", number); else if (errno == ERANGE && number == LONG_MIN) printf (" number : %lu invalid (underflow occurred)\n", number); else if (errno == ERANGE && number == LONG_MAX) printf (" number : %lu invalid (overflow occurred)\n", number); else if (errno == EINVAL) /* not in all c99 implementations - gcc OK */ printf (" number : %lu invalid (base contains unsupported value)\n", number); else if (errno != 0 && number == 0) printf (" number : %lu invalid (unspecified error occurred)\n", number); else if (errno == 0 && nptr && !*endptr) printf (" number : %lu valid (and represents all characters read)\n", number); else if (errno == 0 && nptr && *endptr != 0) printf (" number : %lu valid (but additional characters remain)\n", number); printf ("\n"); return 0; } 

sortie:

 $ ./bin/s2lv 578231 ssortingng : 578231 base : 10 endptr : number : 578231 valid (and represents all characters read) $ ./bin/s2lv 578231_w_additional_chars ssortingng : 578231_w_additional_chars base : 10 endptr : _w_additional_chars number : 578231 valid (but additional characters remain) $ ./bin/s2lv 578some2more3stuff1 ssortingng : 578some2more3stuff1 base : 10 endptr : some2more3stuff1 number : 578 valid (but additional characters remain) $ ./bin/s2lv 00000000000000000 ssortingng : 00000000000000000 base : 10 endptr : number : 0 valid (and represents all characters read) $ ./bin/s2lv stuff578231 ssortingng : stuff578231 base : 10 endptr : stuff578231 number : 0 invalid (no digits found, 0 returned) $ ./bin/s2lv 00000000000000000 -2 ssortingng : 00000000000000000 base : -2 endptr : (null) number : 0 invalid (base contains unsupported value)