Question

J'ai un grand nombre stocké dans une chaîne et tente d'extraire un seul chiffre. Mais quelles sont les différences entre ces appels?

#include <iostream>
#include <string>

int main(){
    std::string bigNumber = "93485720394857230";
    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);
    int digit2 = atoi(&bigNumber.at(5))
    int digit3 = atoi(&bigNumber.at(12));
    std::cout << "digit: " << digit << std::endl;
    std::cout << "digit2: " << digit2 << std::endl;
    std::cout << "digit3: " << digit3 << std::endl;
}

Ceci produira la sortie suivante.

  

chiffre: 7

     

chiffre2: 2147483647

     

digit3: 57230

Le premier correspond au résultat souhaité. Le second me semble être un nombre aléatoire que je ne trouve pas dans la chaîne. Le troisième est la fin de la chaîne, mais pas seulement un chiffre comme je l’attendais, mais à partir du 12e index jusqu’à la fin de la chaîne. Quelqu'un peut-il m'expliquer les différentes sorties?

EDIT: Serait-ce une solution acceptable?

char tmp[2] = {bigNumber.at(5), '\0'};
int digit = atoi(tmp);
std::cout << "digit: " << digit << std::endl;
Était-ce utile?

La solution

Tout est plus ou moins explicable.

int main(){
    std::string bigNumber = "93485720394857230";

Cette ligne copie le caractère unique "5" dans la variable de caractère. atoi le convertira correctement. atoi s'attend à ce que le paramètre de chaîne soit une chaîne 0 valide. & amp; tmp n'est qu'un pointeur sur la variable de caractère. Le comportement de cet appel n'est pas défini car la mémoire qui suit immédiatement le caractère en mémoire est inconnue. Pour être exact, vous devez créer une chaîne terminée par null et la transmettre. *

    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);

Cette ligne obtient un pointeur sur le caractère situé à la position 5 de la chaîne. Il s’agit d’un pointeur dans la chaîne de grand nombre d’origine ci-dessus - le paramètre de chaîne atoi ressemble donc à la chaîne "5720394857230". atoi essaiera clairement de transformer cela en un entier car aucun entier de 32 bits ne le tiendra.

    int digit2 = atoi(&bigNumber.at(5))

Cette ligne obtient un pointeur dans la chaîne à la position 12. Le paramètre pour atoi est la chaîne "57230". Ceci est converti correctement dans le nombre entier 57230.

    int digit3 = atoi(&bigNumber.at(12));

...     }

Puisque vous utilisez C ++, il existe de meilleures méthodes pour convertir des chaînes de caractères en entiers. La bibliothèque Boost lexical_cast est l’une de mes particularités. Vous l'utiliseriez comme ceci:

char tmp = bigNumber.at(5);
// convert the character to a string then to an integer
int digit = boost::lexical_cast<int>(std::string(tmp));

// this copies the whole target string at position 5 and then attempts conversion
// if the conversion fails, then a bad_lexical_cast is thrown
int digit2=boost::lexical_cast<int>(std::string(bigNumber.at(5)));

* Strictement, atoi va parcourir les caractères numériques jusqu'à ce qu'ils en trouvent un non-numérique. Il est clairement indéterminé de savoir quand il en trouvera un et ce qu’il fera lorsqu’il lira des emplacements mémoire invalides.

Autres conseils

Je sais pourquoi le deuxième chiffre est affiché.

à partir de la référence atoi.

  

Si la valeur correcte est en dehors de la plage des valeurs pouvant être représentées, INT_MAX ou INT_MIN est renvoyé.

2147483647 est INT_MAX

bigNumber.at () ne renvoie pas une nouvelle chaîne avec un seul caractère mais l'adresse d'un caractère dans la chaîne. Donc, le deuxième appel est en réalité:

atoi("720394857230")

ce qui provoque un débordement de l'algorithme interne.

De plus, le premier appel est très dangereux car il dépend de la valeur (aléatoire) en mémoire à (& amp; tmp) +1 .

Vous devez attribuer une chaîne de deux caractères, attribuer le caractère unique de bigNumber.at () au premier et \ 0 au second, puis appeler < code> atoi () avec l'adresse de la chaîne temporaire.

L'argument de atoi doit être une chaîne terminée par zéro.

La fonction dans donne un pointeur sur char dans la chaîne. La fonction atoi convertit la chaîne en entier, et non en un seul caractère.

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