Comment déterminer si une chaîne est un nombre avec C ++?

136

J'ai eu un peu de mal à essayer d'écrire une fonction qui vérifie si une chaîne est un nombre. Pour un jeu que j'écris, j'ai juste besoin de vérifier si une ligne du fichier que je lis est un nombre ou non (je saurai si c'est un paramètre de cette façon). J'ai écrit la fonction ci-dessous qui, je pense, fonctionnait correctement (ou j'ai accidentellement modifié pour l'arrêter ou je suis schizophrène ou Windows est schizophrène):

bool isParam (string line)
{
    if (isdigit(atoi(line.c_str())))
        return true;

    return false;
}
Brendan Weinstein
la source
184
Je déteste voir if (expr) return true; return false;! Écrivez juste return expr;.
éphémient
17
@ephemient Mon style est de faire la même chose que vous. Mais est-ce vraiment un gros problème?
Brennan Vincent
2
Votre prototype de fonction ne semble pas approprié. Pourquoi ne pas utiliser bool isParam (const string & line)
MikimotoH
4
Ouais. J'ai une mauvaise habitude de coder en style long lors de l'apprentissage d'une nouvelle langue. Je suis nouveau sur C ++ et plus hésitant sur les "raccourcis" (ou raccourcis perçus).
Brendan Weinstein
57
@Brennan Vincent: Oui, c'est un gros problème. Il est de la même classe d'erreurs que if (expr) return expr; else return expr;, if (expr == true), (if expr != false), ou if ((expr == true) == true). Ils introduisent tous une complexité qui ne profite pas à l'écrivain, au lecteur ou au compilateur du code. L'élimination de la complexité inutile n'est pas un raccourci; c'est la clé pour écrire de meilleurs logiciels.
MSalters

Réponses:

148

Le moyen le plus efficace serait simplement de parcourir la chaîne jusqu'à ce que vous trouviez un caractère non numérique. S'il y a des caractères non numériques, vous pouvez considérer la chaîne comme un nombre.

bool is_number(const std::string& s)
{
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}

Ou si vous voulez le faire de la manière C ++ 11:

bool is_number(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(), 
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

Comme indiqué dans les commentaires ci-dessous, cela ne fonctionne que pour les entiers positifs. Si vous avez besoin de détecter des entiers ou des fractions négatifs, vous devriez opter pour une solution basée sur une bibliothèque plus robuste. Cependant, l'ajout de la prise en charge des entiers négatifs est assez trivial.

Charles Salvia
la source
6
Ne gère pas non plus les nombres négatifs et les nombres non entiers. Nous ne pouvons pas savoir quelles sont les exigences basées sur la question.
Brennan Vincent
76
Vous pouvez également utiliser !s.empty() && s.find_first_not_of("0123456789") == std::string::npos;pour un one-liner C ++ 03.
kbjorklu
8
Ne gère pas non plus les nombres décimaux, par exemple: 1,23
littlecodefarmer758
3
@Remy Lebeau, oui. Il ne s'agit pas de convertir la chaîne en un fichier int. Il s'agit simplement d'identifier si une chaîne est composée de chiffres numériques. La longueur de la chaîne n'a pas d'importance.
Charles Salvia
5
N'oubliez pas d'inclure <string> <algorithm>et <cctype>de faire fonctionner l'exemple C ++ 11.
kR105
88

Pourquoi réinventer la roue? La bibliothèque standard C (également disponible en C ++) a une fonction qui fait exactement cela:

char* p;
long converted = strtol(s, &p, 10);
if (*p) {
    // conversion failed because the input wasn't a number
}
else {
    // use converted
}

Si vous souhaitez gérer les fractions ou la notation scientifique, utilisez strtodplutôt (vous obtiendrez un doublerésultat).

Si vous souhaitez autoriser les constantes hexadécimales et octales dans le style C / C ++ ( "0xABC"), définissez le dernier paramètre à la 0place.

Votre fonction peut alors être écrite comme

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}
Ben Voigt
la source
4
Cette fonction supprime l'espace blanc devant. Vous devez donc vérifier le premier caractère pour isdigit.
chmike
1
@chmike: D'après ma compréhension de la question, supprimer les espaces de début est le comportement correct ( atoitel qu'utilisé dans la question le fait également).
Ben Voigt
1
La question ne le spécifiait pas explicitement, mais ma compréhension de l'exigence "vérifie si une chaîne est un nombre" signifie que la chaîne entière est le nombre, donc pas d'espaces. J'ai ressenti le besoin de souligner que votre réponse est différente des autres à cet égard. Votre réponse peut être correcte s'il est correct pour la chaîne d'avoir des espaces devant le nombre.
chmike
1
@BenVoigt Vous dites que ce psera réglé sur nullptrsi strtolc'est réussi, non? Ce n'est pas ce que je vois :(
Jonathan Mee
2
@JonathanMee: Non, ppointera vers le NUL qui termine la chaîne. Alors p != 0et *p == 0.
Ben Voigt
33

Avec le compilateur C ++ 11, pour les entiers non négatifs, j'utiliserais quelque chose comme ça (notez le ::au lieu de std::):

bool is_number(const std::string &s) {
  return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
}

http://ideone.com/OjVJWh

szx
la source
1
C'est la meilleure réponse.
Martin Broadhurst
S'il y a des caractères utf8 dans la chaîne, vous obtiendrez une erreur d'exécution.
Lion King
29

Vous pouvez le faire de la manière C ++ avec boost :: lexical_cast. Si vous insistez vraiment pour ne pas utiliser boost, vous pouvez simplement examiner ce qu'il fait et le faire. C'est assez simple.

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }
Edward étrange
la source
21
Vous utilisez try{} catch{}une bonne idée? Ne devrait-on pas l'éviter autant que possible?
Nawaz
32
-1 pour abuser de try catch ... blogs.msdn.com/b/ericlippert/archive/2008/09/10/…
NoSenseEtAl
14
try {} catch {} est approprié ici. Cependant, attraper (...) est juste une mauvaise pratique. Dans ce cas, utilisez boost :: bad_lexical_cast pour votre gestionnaire d'exceptions.
NuSkooler
5
J'ai l'impression que cela essaie de lire à partir d'un fichier. Peu importe combien de vérifications vous faites sur le fichier, vous ne saurez pas s'il est possible de le lire jusqu'à ce que vous le fassiez. Cela fonctionnera ou non. Dans ce cas, vous devrez intercepter une exception. Donc, dans ce cas, je pense que c'est une très bonne façon de le faire.
Casey
4
@EarlGray - Je serais certainement intéressé de savoir quelles actions dépendantes du système d'exploitation prendraient les fenêtres. La norme est assez claire sur la manière dont ce code doit se comporter.
Edward Strange
16

Je voulais juste ajouter cette idée qui utilise l'itération, mais un autre code fait cette itération:

#include <string.h>

bool is_number(const std::string& s)
{
    return( strspn( s.c_str(), "-.0123456789" ) == s.size() );
}

Ce n'est pas robuste comme il se doit lors de la vérification d'un point décimal ou d'un signe moins car il permet qu'il y en ait plus d'un de chaque et à n'importe quel endroit. La bonne chose est qu'il s'agit d'une seule ligne de code et ne nécessite pas de bibliothèque tierce.

Retirez le "." et '-' si seuls les entiers positifs sont autorisés.

David Recteur
la source
erreur: 'strspn' n'a pas été déclaré dans cette étendue Je pense que c'est parce qu'il me manque un "#include" mais quel est-il
Qwertie
4
Si vous comptez utiliser std::string, utilisez sa find_first_not_offonction membre.
Ben Voigt
5
Cela échouerait si vous passiez une chaîne de "12.3-4.55-", qui n'est évidemment pas un nombre valide
Buzzrick
Buzzrick, la réponse proposée indique déjà que cela échouerait avec le non-numéro que vous avez mentionné.
David Rector
si vous le limitez uniquement à "0123456789", alors la formule est parfaite pour tester les nombres entiers non signés
pas de spécial
16

Je suggérerais une approche regex. Une regex-match complète (par exemple, en utilisant boost :: regex ) avec

-?[0-9]+([\.][0-9]+)?

montrerait si la chaîne est un nombre ou non. Cela comprend les nombres positifs et négatifs, les nombres entiers et les nombres décimaux.

Autres variantes:

[0-9]+([\.][0-9]+)?

(seulement positif)

-?[0-9]+

(seulement entier)

[0-9]+

(seulement entier positif)

Méphane
la source
Euh, j'ai essayé d'utiliser std::regexavec gcc 4.7, gcc 4.8 - ils lancent tous les deux std::regex_errorsur n'importe quel signe de l' [expression rationnelle, même pour un innocent "[abc]" (est-ce que je fais ça mal?). clang-3.4 n'est pas du <regex>tout au courant . Quoi qu'il en soit, cela semble être la réponse la plus saine, +1.
Dmytro Sirenko
3
@EarlGray: Regex n'est disponible correctement qu'à partir de GCC 4.9
Courses de légèreté en orbite le
13

Voici une autre façon de le faire en utilisant la <regex>bibliothèque:

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}
mpataki14
la source
Ah, ce serait le cas. J'ai mis à jour avec une meilleure solution. Merci.
mpataki14
Ne devrait-il pas être "[(- | +) |] [0-9] +" (plus au lieu d'étoile), sinon votre regex pourrait correspondre sur "-" ou "+" comme un nombre valide.
David Mulder
Agréable. Je ne suis pas sûr de ce que font les (, | et) dans cette première classe de caractères - ces métacaractères perdent leur signification particulière dans une classe de caractères pour autant que je sache. Que diriez-vous de "^ [- +]? [0-9] + $"?
U007D
Cela peut être inefficace. Chaque fois que cela est appelé, il appelle le constructeur std :: regex qui compile l'expression régulière.
user31264
12

Avec cette solution, vous pouvez tout vérifier, des nombres négatifs aux nombres positifs et même des nombres flottants. Lorsque vous modifiez le type de numen entier, vous obtiendrez une erreur si la chaîne contient un point.

#include<iostream>
#include<sstream>
using namespace std;


int main()
{
      string s;

      cin >> s;

      stringstream ss;
      ss << s;

      float num = 0;

      ss >> num;

      if(ss.good()) {
          cerr << "No Valid Number" << endl;
      }
      else if(num == 0 && s[0] != '0') {
          cerr << "No Valid Number" << endl;
      }
      else {
          cout << num<< endl;
      }             
}

Prouver: programme C ++

tzwickl
la source
10

J'ai trouvé le code suivant le plus robuste (c ++ 11). Il attrape à la fois les entiers et les flottants.

#include <regex>
bool isNumber( std::string token )
{
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}
dk123
la source
Il semble que la ligne using namespace std;soit inutile.
Xam
5

Voici une solution pour vérifier les entiers positifs:

bool isPositiveInteger(const std::string& s)
{
    return !s.empty() && 
           (std::count_if(s.begin(), s.end(), std::isdigit) == s.size());
}
Jaime Soto
la source
5

Essaye ça:

isNumber(const std::string &str) {    
  return !str.empty() && str.find_first_not_of("0123456789") == string::npos;
}
Tomasz
la source
1
Ceci teste uniquement les entiers non signés
pas de spécial
4

Brendan ceci

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

est presque ok.

en supposant que toute chaîne commençant par 0 est un nombre, ajoutez simplement une vérification pour ce cas

bool isNumber(const string &line) 
{
 if (line[0] == '0') return true;
 return (atoi(line.c_str()));
}

ofc "123hello" retournera vrai comme l'a noté Tony D.

Noam Geffen
la source
3

Le plus simple auquel je puisse penser en C ++

bool isNumber(string s) {
    if(s.size()==0) return false;
    for(int i=0;i<s.size();i++) {
        if((s[i]>='0' && s[i]<='9')==false) {
            return false;
        }
    }
    return true;
}

Exemple de code de travail: https://ideone.com/nRX51Y

Abhijit Annaldas
la source
3

Ma solution utilisant C ++ 11 regex ( #include <regex>), elle peut être utilisée pour une vérification plus précise, comme unsigned int, doubleetc.:

static const std::regex INT_TYPE("[+-]?[0-9]+");
static const std::regex UNSIGNED_INT_TYPE("[+]?[0-9]+");
static const std::regex DOUBLE_TYPE("[+-]?[0-9]+[.]?[0-9]+");
static const std::regex UNSIGNED_DOUBLE_TYPE("[+]?[0-9]+[.]?[0-9]+");

bool isIntegerType(const std::string& str_)
{
  return std::regex_match(str_, INT_TYPE);
}

bool isUnsignedIntegerType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_INT_TYPE);
}

bool isDoubleType(const std::string& str_)
{
  return std::regex_match(str_, DOUBLE_TYPE);
}

bool isUnsignedDoubleType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_DOUBLE_TYPE);
}

Vous pouvez trouver ce code sur http://ideone.com/lyDtfi , il peut être facilement modifié pour répondre aux exigences.

aniliitb10
la source
Je demanderais aux votes négatifs de m'aider à comprendre le problème, je vais améliorer ma réponse. Merci.
aniliitb10
2

Une solution basée sur un commentaire de kbjorklu est:

bool isNumber(const std::string& s)
{
   return !s.empty() && s.find_first_not_of("-.0123456789") == std::string::npos;
}

Comme avec la réponse de David Rector, elle n'est pas robuste aux chaînes avec plusieurs points ou signes moins, mais vous pouvez supprimer ces caractères pour ne vérifier que les entiers.


Cependant, je suis partisan d'une solution, basée sur la solution de Ben Voigt , utilisant strtoddans cstdlib pour rechercher des valeurs décimales, la notation scientifique / technique, la notation hexidécimale (C ++ 11), ou même INF / INFINITY / NAN (C ++ 11) est:

bool isNumberC(const std::string& s)
{
    char* p;
    strtod(s.c_str(), &p);
    return *p == 0;
}
chappjc
la source
2

Nous pouvons utiliser une classe stringstream .

    bool isNumeric(string str)
    {
       stringstream stream;                   
       double number;

       stream<<str;
       stream>>number;

       return stream.eof();
    }
éruptions cutanées
la source
2

Utilisation <regex>. Ce code a été testé!

bool isNumber(const std::string &token)
{
    return std::regex_match(token, std::regex("(\\+|-)?[0-9]*(\\.?([0-9]+))$"));
}
Nery Jr
la source
1

Après avoir consulté un peu plus la documentation, j'ai trouvé une réponse qui répond à mes besoins, mais qui ne sera probablement pas aussi utile pour les autres. Le voici (sans le retour ennuyeux true et return false déclarations :-))

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}
Brendan Weinstein
la source
4
Si le nombre se trouve être 0, vous obtiendrez un faux négatif.
Charles Salvia
3
Cela renverra n'importe quel nombre de tête, et ne vous avertira pas des déchets de fin (par exemple "123hello" ==> 123). @Charles: Brendan mentionne qu'il n'a qu'à reconnaître les points positifs dans un commentaire sur une autre réponse.
Tony Delroy
1

Je pense que cette expression régulière devrait gérer presque tous les cas

"^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"

donc vous pouvez essayer la fonction suivante qui peut fonctionner avec les deux (Unicode et ANSI)

bool IsNumber(CString Cs){
Cs.Trim();

#ifdef _UNICODE
std::wstring sr = (LPCWSTR)Cs.GetBuffer(Cs.GetLength());
return std::regex_match(sr, std::wregex(_T("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?")));

#else
    std::string s = (LPCSTR)Cs.GetBuffer();
return std::regex_match(s, std::regex("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"));
#endif
}
Motaz
la source
1
include <string>

Pour valider les doubles:

bool validateDouble(const std::string & input) {
int decimals = std::count(input.begin(), input.end(), '.'); // The number of decimals in the string
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == decimals + negativeSigns) // Consists of only decimals and negatives or is empty
    return false;
else if (1 < decimals || 1 < negativeSigns) // More than 1 decimal or negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-.0123456789") != input.size()) // The string contains a character that isn't in "-.0123456789"
    return false;
return true;

}

Pour valider les nombres entiers (avec négatifs)

bool validateInt(const std::string & input) {
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == negativeSigns) // Consists of only negatives or is empty
    return false;
else if (1 < negativeSigns) // More than 1 negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-0123456789") != input.size()) // The string contains a character that isn't in "-0123456789"
    return false;
return true;

}

Pour valider les entiers non signés

bool validateUnsignedInt(const std::string & input) {
return (input.size() != 0 && strspn(input.c_str(), "0123456789") == input.size()); // The string is not empty and contains characters only in "0123456789"

}

Erik Nordin
la source
1
bool isNumeric(string s){
    if ( !s.empty() && s[0] != '-' )
        s = "0" + s; //prepend 0

    string garbage;

    stringstream ss(s); 
    ss >> *(auto_ptr<double>(new double)) >> garbage;
/*
//the line above extracts the number into an anonymous variable. it could also be done like this:
double x;
ss >> x >> garbage;
*/
    //if there is no garbage return true or else return false
    return garbage.empty(); 
}

comment cela fonctionne: la surcharge de stringstream >> peut convertir des chaînes en différents types arithmétiques, elle le fait en lisant les caractères séquentiellement à partir du stringstream (ss dans ce cas) jusqu'à ce qu'il manque de caractères OU le caractère suivant ne répond pas aux critères à stocker dans le type de variable de destination.

Exemple 1:

stringstream ss("11");
double my_number;
ss >> my_number; //my number = 11

exemple2:

stringstream ss("011");
double my_number;
ss >> my_number; //my number = 11

exemple3:

stringstream ss("11ABCD");
double my_number;
ss >> my_number; //my number = 11 (even though there are letters after the 11)

l'explication de la variable "garbage" ":

pourquoi ne pas simplement vérifier si l'extraction dans mon double a une valeur valide, puis retourner true si c'est le cas?

Remarquez que l'exemple3 ci-dessus lira toujours avec succès le numéro 11 dans la variable my_number même si la chaîne d'entrée est "11ABCD" (qui n'est pas un nombre).

pour gérer ce cas, nous pouvons faire une autre extraction dans une variable de chaîne (que j'ai nommée garbage) qui peut lire tout ce qui peut avoir été laissé dans le tampon de chaîne après l'extraction initiale dans la variable de type double. S'il reste quelque chose, il sera lu dans "garbage", ce qui signifie que la chaîne complète passée n'est pas un nombre (elle commence juste par un). dans ce cas, nous voudrions retourner false;

l'explication "0" préfixée:

tenter d'extraire un seul caractère dans un double échouera (renvoyer 0 dans notre double) mais déplacera toujours la position du tampon de chaîne après le caractère. Dans ce cas, notre lecture garbage sera vide, ce qui entraînerait le retour incorrect de la fonction true. pour contourner cela, j'ai ajouté un 0 à la chaîne de sorte que si, par exemple, la chaîne passée était "a", elle soit changée en "0a" afin que le 0 soit extrait dans le double et "a" soit extrait dans les ordures.

l'ajout d'un 0 n'affectera pas la valeur du nombre, donc le nombre sera toujours correctement extrait dans notre variable double.

KorreyD
la source
1
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la raison et / ou la manière dont ce code répond à la question améliore sa valeur à long terme.
Ajean
1

pour vérifier si une chaîne est un nombre entier ou une virgule flottante ou si vous pouvez utiliser:

 #include <sstream>

    bool isNumber(string str) {
    double d;
    istringstream is(str);
    is >> d;
    return !is.fail() && is.eof();
}
MuhammadKhalifa
la source
1
cela renverra 10 pour une chaîne contenant la valeur "10_is_not_a_number".
KorreyD
1

Encore une autre réponse, qui utilise stold(bien que vous puissiez également utiliser stof/ stodsi vous n'avez pas besoin de la précision).

bool isNumeric(const std::string& string)
{
    std::size_t pos;
    long double value = 0.0;

    try
    {
        value = std::stold(string, &pos);
    }
    catch(std::invalid_argument&)
    {
        return false;
    }
    catch(std::out_of_range&)
    {
        return false;
    }

    return pos == string.size() && !std::isnan(value);
}
Tim Angus
la source
1

Essaye ça:

bool checkDigit(string str)
{  
   int n=str.length();

   for(int i=0;    i   < n ;   i++)
   {
     if(str[i]<'0' || str[i]>'9')
       return false;
   }

   return true;
}
rrlinus
la source
1

Vous pouvez tester si une chaîne est convertible en entier en utilisant boost :: lexical_cast . S'il lève une exception bad_lexical_cast, la chaîne ne peut pas être convertie, sinon elle le peut.

Voir l'exemple d'un tel programme de test ci-dessous:

#include <boost/lexical_cast.hpp>
#include <iostream>

int main(int, char** argv)
{
        try
        {
                int x = boost::lexical_cast<int>(argv[1]);
                std::cout << x << " YES\n";
        }
        catch (boost::bad_lexical_cast const &)
        {
                std:: cout << "NO\n";
        }
        return 0;
}

Exemple d'exécution:

# ./a.out 12
12 YES
# ./a.out 12/3
NO
Łukasz Ślusarczyk
la source
0

Il y a quelques mois, j'ai implémenté un moyen de déterminer si une chaîne est un entier, un hexadécimal ou un double.

enum{
        STRING_IS_INVALID_NUMBER=0,
        STRING_IS_HEXA,
        STRING_IS_INT,
        STRING_IS_DOUBLE
};

bool isDigit(char c){
    return (('0' <= c) && (c<='9'));
}

bool isHexaDigit(char c){
    return ((('0' <= c) && (c<='9')) || ((tolower(c)<='a')&&(tolower(c)<='f')));
}


char *ADVANCE_DIGITS(char *aux_p){

    while(CString::isDigit(*aux_p)) aux_p++;
    return aux_p;
}

char *ADVANCE_HEXADIGITS(char *aux_p){

    while(CString::isHexaDigit(*aux_p)) aux_p++;
    return aux_p;
}


int isNumber(const string & test_str_number){
    bool isHexa=false;
    char *str = (char *)test_str_number.c_str();

    switch(*str){
    case '-': str++; // is negative number ...
               break;
    case '0': 
              if(tolower(*str+1)=='x')  {
                  isHexa = true;
                  str+=2;
              }
              break;
    default:
            break;
    };

    char *start_str = str; // saves start position...
    if(isHexa) { // candidate to hexa ...
        str = ADVANCE_HEXADIGITS(str);
        if(str == start_str)
            return STRING_IS_INVALID_NUMBER;

        if(*str == ' ' || *str == 0) 
            return STRING_IS_HEXA;

    }else{ // test if integer or float
        str = ADVANCE_DIGITS(str);
        if(*str=='.') { // is candidate to double
            str++;
            str = ADVANCE_DIGITS(str);
            if(*str == ' ' || *str == 0)
                return STRING_IS_DOUBLE;

            return STRING_IS_INVALID_NUMBER;
        }

        if(*str == ' ' || *str == 0)
            return STRING_IS_INT;

    }

    return STRING_IS_INVALID_NUMBER;


}

Ensuite, dans votre programme, vous pouvez facilement convertir le nombre en fonction de son type si vous procédez comme suit,

string val; // the string to check if number...

switch(isNumber(val)){
   case STRING_IS_HEXA: 
   // use strtol(val.c_str(), NULL, 16); to convert it into conventional hexadecimal
   break;
   case STRING_IS_INT: 
   // use (int)strtol(val.c_str(), NULL, 10); to convert it into conventional integer
   break;
   case STRING_IS_DOUBLE:
   // use atof(val.c_str()); to convert it into conventional float/double
   break;
}

Vous pouvez réaliser que la fonction renverra un 0 si le nombre n'a pas été détecté. Le 0 il peut être traité comme faux (comme booléen).

Jordi Espada
la source
0

Je propose une convention simple:

Si la conversion en ASCII est> 0 ou si elle commence par 0, alors c'est un nombre. Ce n'est pas parfait mais rapide.

Quelque chose comme ça:

string token0;

if (atoi(token0.c_str())>0 || isdigit(token0.c_str()[0]) ) { //this is a value
    // do what you need to do...
}
Gokhan Unel
la source
0

Cette fonction prend en charge tous les cas possibles:

bool AppUtilities::checkStringIsNumber(std::string s){
    //Eliminate obvious irritants that could spoil the party
    //Handle special cases here, e.g. return true for "+", "-", "" if they are acceptable as numbers to you
    if (s == "" || s == "." || s == "+" || s == "-" || s == "+." || s == "-.") return false;

    //Remove leading / trailing spaces **IF** they are acceptable to you
    while (s.size() > 0 && s[0] == ' ') s = s.substr(1, s.size() - 1);
    while (s.size() > 0 && s[s.size() - 1] == ' ') s = s.substr(0, s.size() - 1);


    //Remove any leading + or - sign
    if (s[0] == '+' || s[0] == '-')
        s = s.substr(1, s.size() - 1);

    //Remove decimal points
    long prevLength = s.size();

    size_t start_pos = 0;
    while((start_pos = s.find(".", start_pos)) != std::string::npos) 
        s.replace(start_pos, 1, "");

    //If the string had more than 2 decimal points, return false.
    if (prevLength > s.size() + 1) return false;

    //Check that you are left with numbers only!!
    //Courtesy selected answer by Charles Salvia above
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();

    //Tada....
}
Vaibhav Gupta
la source
0

Pourriez-vous simplement utiliser le code de retour de sscanf pour déterminer s'il s'agit d'un int?

bool is_number(const std::string& s)
{
    int value;
    int result = sscanf(valueStr.c_str(), "%d", &value);
    return (result != EOF && readResult != 0);
}
David D
la source