Pourquoi ai-je ce résultat inattendu en utilisant atoi () en C?

Je ne comprends pas les résultats du code C suivant.

main() { char s[] = "AAA"; advanceSsortingng(s); } void advanceSsortingng(p[3]) { int val = atoi(p); printf("The atoi val is %d\n",val); } 

Ici, la valeur atoi est indiquée par 0, mais je ne peux pas en comprendre la raison exacte. Selon ma compréhension, cela devrait-il être la sum de l’équivalent décimal de chaque valeur du tableau? S’il vous plait corrigez moi si je me trompe.

atoi() convertit la représentation sous forme de chaîne d’un entier en sa valeur. Il ne convertira pas les caractères arbitraires en valeurs décimales. Par exemple:

 int main(void) { const char *ssortingng="12345"; printf("The value of %s is %d\n", ssortingng, atoi(ssortingng)); return 0; } 

Rien dans la bibliothèque C standard ne permet de convertir “A” en 65 ou “Z” en 90; vous devez écrire cela vous-même, en particulier pour le jeu de caractères que vous attendez en tant qu’entrée.

Maintenant que vous savez ce que fait atoi() , ne l’utilisez pas pour traiter les entrées numériques dans tout ce que vous proposez. Vous devez vraiment faire en sorte que vos commentaires ne soient pas ce que vous attendez. Hmm, que se passe-t-il quand j’entre 65 au lieu de A? Les enseignants aiment casser des choses.

atoi() ne fait aucune erreur de vérification, ce qui rend tout ce qui est fiable pour convertir des entrées arbitraires, au mieux. À la place, utilisez strtol() (exemple centré sur POSIX):

 #include  #include  #include  int main(void) { static const char *input ="123abc"; char *garbage = NULL; long value = 0; errno = 0; value = strtol(input, &garbage, 0); switch (errno) { case ERANGE: printf("The data could not be represented.\n"); return 1; // host-specific (GNU/Linux in my case) case EINVAL: printf("Unsupported base / radix.\n"); return 1; } printf("The value is %ld, leftover garbage in the ssortingng is %s\n", // Again, host-specific, avoid trying to print NULL. value, garbage == NULL ? "N/A" : garbage); return 0; } 

Lorsqu’il est exécuté, cela donne:

La valeur est 123, les déchets restants dans la chaîne sont abc

Si vous ne vous souciez pas de sauvegarder / examiner la corbeille, vous pouvez définir le deuxième argument sur NULL . Il n’y a pas besoin de free(garbage) . Notez également que si vous passez 0 comme troisième argument, il est supposé que l’entrée correspond à la valeur souhaitée d’une représentation décimale, hexadécimale ou octale. Si vous avez besoin d’une base de 10, utilisez 10 – elle échouera si l’entrée ne correspond pas à vos attentes.

Vous devriez également vérifier la valeur de retour pour la valeur maximale et minimale qu’un long int peut gérer. Toutefois, si l’un ou l’autre est renvoyé pour indiquer une erreur, errno code d’erreur. Un exercice pour le lecteur consiste à modifier *input de 123abc en abc123 .

Il est important de vérifier le retour, car votre exemple montre ce qui se passe si vous ne le faites pas. AbcDeFg n’est pas une représentation sous forme de chaîne d’un entier et vous devez en tenir compte dans votre fonction.

Pour votre mise en œuvre, le conseil le plus fondamental que je puisse vous donner serait une série de commutateurs, quelque chose comme:

 // signed, since a return value of 0 is acceptable (NULL), -1 // means failure int ascii_to_ascii_val(const char *in) { switch(in) { // 64 other cases before 'A' case 'A': return 65; // keep going from here default: return -1; // failure } 

.. puis juste exécuter cela dans une boucle.

Ou pré-remplir un dictionnaire qu’une fonction de recherche pourrait définir (mieux). Vous n’avez pas besoin de hachages, mais simplement d’un magasin de valeurs -> puisque vous savez ce qu’il va contenir à l’avance, où les caractères ASCII standard sont des clés et leurs identificateurs correspondants sont des valeurs.

Il essaie de convertir la chaîne en un entier. Puisque AAA ne peut pas être converti en un entier, la valeur est 0. Essayez de lui donner 42 ou quelque chose.

Si aucune conversion valide ne peut être effectuée, une valeur zéro est renvoyée.

Voir http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

Lisez atoi() comme un to i (ASCII en entier).

atoi() convertit une chaîne représentant un nombre décimal, en entier.

 char s[] = "42"; int num = atoi(s); //The value of num is 42. 

atoi s’attend à ce que son argument soit une représentation sous forme de chaîne d’une constante entière décimale (base-10); AAA n’est pas une constante entière décimale valide. atoi conséquent, atoi renvoie 0 car il n’a aucun autre moyen d’indiquer que l’entrée est invalide.

Notez que atoi convertira le premier caractère qui ne fait pas partie d’une constante entière valide. autrement dit, “123” et “123w” seront tous deux convertis en 123.

Comme tout le monde le dit, n’utilisez pas atoi ; utilisez strtol place.