178 votes

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

J'ai eu beaucoup de mal à écrire une fonction qui vérifie si une chaîne de caractères 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 crois, fonctionnait sans problème (ou j'ai accidentellement édité 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;
}

188voto

Charles Salvia Points 28661

Le moyen le plus efficace serait d'itérer sur 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 que la chaîne n'est pas 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 à la manière de C++11 :

bool is_number(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(), 
        s.end(), [](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 négatifs ou des fractions, vous devez opter pour une solution plus robuste basée sur une bibliothèque. Bien que l'ajout de la prise en charge des entiers négatifs soit assez trivial.

118voto

Ben Voigt Points 151460

Pourquoi réinventer la roue ? La bibliothèque standard du C (disponible également en C++) possède 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, optez pour l'option strtod à la place (vous obtiendrez un double résultat).

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

Votre fonction peut alors s'écrire comme suit

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}

33voto

Crazy Eddie Points 23778

Vous pouvez le faire à la manière de C++ avec boost::lexical_cast. Si vous tenez vraiment à 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 }

21voto

David Rector Points 103

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

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

Il n'est pas robuste comme il devrait l'être lorsqu'il s'agit de vérifier la présence d'un point décimal ou d'un signe moins, puisqu'il permet qu'il y ait plus d'un de chaque et à n'importe quel endroit. L'avantage est qu'il s'agit d'une simple ligne de code et qu'il n'est pas nécessaire d'utiliser une bibliothèque tierce.

Enlevez le "." et le "-" si les nombres entiers positifs sont les seuls autorisés.

14voto

tom1991te Points 172

Avec cette solution, vous pouvez tout vérifier, des nombres négatifs aux nombres positifs et même les nombres flottants. Lorsque vous changez le type de num en 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;
      }             
}

Prouve-le : Programme C++

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X