Comment savoir si la fonction c atoi a échoué ou s'il s'agissait d'une chaîne de zéros?

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

  •  08-07-2019
  •  | 
  •  

Question

Lorsque vous utilisez la fonction atoi (ou strtol ou des fonctions similaires), comment savoir si la conversion d'entier a échoué ou si la chaîne de caractères C en cours de conversion était un 0 ?

Pour ce que je fais, 0 est une valeur acceptable et la chaîne C en cours de conversion peut contenir un nombre quelconque de 0 . Il se peut également qu’il y ait des espaces en tête.

Était-ce utile?

La solution

Pour C ++ 11 et versions ultérieures:

La fonction de référence pour la conversion de chaîne en entier est désormais stoi , qui prend une chaîne et renvoie un int , ou lève une exception en cas d'erreur.

Plus besoin du piratage istringstream détaillé mentionné dans la réponse acceptée.

(Il y a aussi stol / stoll / stof / stod / stold pour les conversions longues / longues / float / doubles / longues doubles , respectivement .)

Autres conseils

La fonction appropriée (tant que vous insistez sur l'utilisation de fonctions de style C) est strtol et le code de conversion peut se présenter comme suit

const char *number = "10"; /* for example */

char *end;
long value = strtol(number, &end, 10); 
if (end == number || *end != '\0' || errno == ERANGE)
  /* ERROR, abort */;

/* Success */
/* Add whatever range checks you want to have on the value of `value` */

Quelques remarques:

strtol autorise (ce qui signifie: ignore silencieusement) les espaces devant le nombre réel. Si vous voulez traiter une telle espace comme une erreur, vous devez la vérifier vous-même.

La vérification de * end! = '\ 0' garantit qu'il n'y a rien après les chiffres. Si vous souhaitez autoriser d'autres caractères après le nombre réel (espace??), Cette vérification doit être modifiée en conséquence.

P.S. J'ai ajouté la vérification end == number plus tard pour détecter les séquences d'entrée vides. "Tous les espaces" et "pas de numéro du tout" les entrées auraient été interceptées par la seule vérification de * end! = '\ 0' . Cependant, il peut être judicieux d’attraper les entrées vides à l’avance. Dans ce cas, la vérification end == number deviendra / pourrait devenir inutile.

Étant donné que cette balise est étiquetée :

template< typename T >
inline T convert(const std::string& str)
{
    std::istringstream iss(str);
    T obj;

    iss >> std::ws >> obj >> std::ws;

    if(!iss.eof())
        throw "dammit!";

    return obj; 
}

À partir de la page de manuel de strtol ():

  

Si endptr n’est pas NULL, strtol () stocke l’adresse du premier invalide        caractère dans * endptr. S'il n'y avait pas de chiffres, strtol ()        stocke la valeur d'origine de nptr dans * endptr. (Ainsi, si * nptr n’est pas         '\ 0' mais ** endptr est '\ 0' au retour, la chaîne entière était valide.)

Une alternative à strtol est sscanf , bien qu'il soit un peu lourd:

const char *numStr = "12345";  // input string
int value;
if(sscanf(numStr, "%d", &value) == 1)
    ;  // parsing succeeded, use value
else
    ;  // error

Toutefois, cela permet de mettre les espaces blancs en tête dans votre chaîne (ce qui peut être souhaitable ou non), et permet à tout élément de suivre le nombre, donc "123abc". serait accepté et renvoyé 123. Si vous souhaitez un contrôle plus strict, utilisez strtol () , comme Démonstrations d'AndreyT .

Cela fait un moment que je n’ai pas fini de parler en C / C ++, mais il me semblerait que la solution (trop) simple serait de vérifier que la chaîne ne contient pas "0".

int value = atoi(string_number.c_str());

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top