web-dev-qa-db-fra.com

Détermine si une chaîne C est un int valide en C

Je dois vérifier si une chaîne C est un entier valide.

J'ai essayé les deux

int num=atoi(str);

et 

int res=sscanf(str, "%d", &num);

Mais l'envoi de la chaîne "8 -9 10" dans les deux lignes renvoyait simplement 8, sans indiquer l'invalidité de cette chaîne.

Quelqu'un peut-il suggérer une alternative?

19
sara

Regardez strtol (), il peut vous renseigner sur les parties non valides de la chaîne par retour de pointeur.

Et méfiez-vous des exemples de code enthousiastes. Consultez la page de manuel pour une gestion complète des erreurs.

30
blueshift

Je vais peut-être me faire reprocher de ne pas utiliser strtol ou des fonctions similaires libc, mais raisonner à propos de ce problème n'est pas si difficile:

#include <stdbool.h>  // if using C99...  for C++ leave this out.
#include <ctype.h>

bool is_valid_int(const char *str)
{
   // Handle negative numbers.
   //
   if (*str == '-')
      ++str;

   // Handle empty string or just "-".
   //
   if (!*str)
      return false;

   // Check for non-digit chars in the rest of the stirng.
   //
   while (*str)
   {
      if (!isdigit(*str))
         return false;
      else
         ++str;
   }

   return true;
}

[NB: J'aurais peut-être autrement fait isdigit(*str++) au lieu de else pour le raccourcir, mais je me souviens que les normes indiquent qu'il est possible que isdigit soit une macro.]

J'imagine qu'une des limites est que cela ne retourne pas false si le nombre dans la chaîne ne tient pas dans un entier. Cela peut ou peut ne pas avoir d'importance pour vous.

8
asveikau

Un moyen simple de le faire consisterait à lire le fichier int et à vous assurer que la représentation de la chaîne est identique à la chaîne en entrée, en combinant par exemple atoi et itoa:

int is_int(char const* p)
{
    return strcmp(itoa(atoi(p)), p) == 0;
}
2
Inverse

Pour vérifier si la chaîne contient un nombre valide, vous pouvez utiliser une expression régulière. Par exemple, pour les entiers, utilisez:

[- +]? [0-9] +

et un cas général pour les nombres à virgule flottante:

[+ -]? [0-9] + [.]? [0-9] * ([eE] [- +]? [0-9] +)?

Dans le cas de C++ 11, les fonctions d'expression régulière sont disponibles dans la bibliothèque, par ex. "std :: regex_match (.....)" donne la correspondance exacte. Le code devrait ressembler à ceci:

#include <regex>
.....
std::string strnumber("-1.234e+01");
float number;
if(regex_match(strnumber,std::regex("[+-]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?"))
number=std::stof(strnumber);
else
std::cout<<"error, string is not a valid number";
0
Kazik

Désolé de creuser le sujet, mais par souci d'exhaustivité et parce que ce fil est la première correspondance lors d'une recherche google ...

Il est possible d'utiliser quelque chose comme:

ret = sscanf(string, "%d%n", &number, &idx);
if (ret == 0 || string[idx] != '\0')
    /* handle the error */

la directive %n, qui semble être le standard C selon la page de manuel, compte le nombre de caractères traités.

[Edit] sscanf ne semble pas fournir un moyen de détecter les débordements, la famille de fonctions strtoX devrait donc être préférée à mon humble avis.

0
ncarrier