55 votes

comment vérifier si une chaîne ou un char* donné en c++ ne contient que des chiffres ?

Ou dans l'autre sens, trouvez le premier caractère non numérique.

Les mêmes fonctions s'appliquent-elles aux chaînes de caractères et aux char* ?

119voto

Blastfurnace Points 8160

Bien entendu, il existe de nombreuses façons de vérifier qu'une chaîne de caractères ne contient que des caractères numériques. Voici deux méthodes possibles :

bool is_digits(const std::string &str)
{
    return str.find_first_not_of("0123456789") == std::string::npos;
}

o

bool is_digits(const std::string &str)
{
    return std::all_of(str.begin(), str.end(), ::isdigit); // C++11
}

14voto

Dietmar Kühl Points 70604

Plusieurs personnes ont déjà mentionné d'utiliser isdigit() . Cependant, notez que ce n'est pas entièrement trivial car char peut être signé, ce qui entraînerait la transmission d'une valeur négative à l'option isdigit() . Cependant, cette fonction ne peut prendre que des valeurs positives. Autrement dit, vous voulez quelque chose qui ressemble à ceci :

if (s.end() == std::find_if(s.begin(), s.end(),
    [](unsigned char c)->bool { return !isdigit(c); })) {
    std::cout << "string '" << s << "' contains only digits\n";
}

Il semble que le raisonnement pour la conversion à unsigned char n'est pas évident. Voici donc les citations pertinentes de leurs normes respectives :

Selon la norme ISO/CEI 9899:2011 (ou ISO/CEI 9899:1999) 7.4, paragraphe 1, ce qui suit s'applique aux arguments des fonctions from <ctype.h> :

... Dans tous les cas, l'argument est un int dont la valeur est représentable en tant que unsigned char ou est égale à la valeur de la macro EOF . Si l a toute autre valeur, le comportement est indéfini.

Malheureusement, la norme C++ ne précise pas que char est un type non signé. Au lieu de cela, elle spécifie dans l'ISO/IEC 14882:2011 3.9.1 [basic.fundamental] paragraphe 1 :

... Il est défini par l'implémentation si un char peut contenir des valeurs négatives. ...

Il est clair qu'une valeur négative ne peut pas être représentée comme un unsigned char . C'est-à-dire que si char utilise un type signé sur une implémentation (il y en a en fait plusieurs qui le font, par exemple, il est signé sur MacOS en utilisant gcc ou clang), il y a le danger que l'appel de n'importe quel type de la fonction <ctype.h> provoquerait un comportement indéfini.

Maintenant, pourquoi la conversion en unsigned char fait les bonnes choses ?

Selon le point 4.7 [conv.integral], paragraphe 2 :

Si le type de destination est non signé, la valeur résultante est le plus petit entier non signé congruent à l'entier de source (modulo 2 n où n est le nombre de bits utilisés pour représenter le type non signé). [Note : Dans une représentation en complément à deux, cette conversion est conceptuelle et il n'y a pas de changement dans la configuration des bits (s'il n'y a pas de troncature). -fin de la note ]

C'est-à-dire que la conversion d'un fichier [potentiellement] signé char a unsigned char est bien défini et fait en sorte que le résultat se situe dans la plage autorisée pour l'option <ctype.h> fonctions.

5voto

MSN Points 30386

isdigit(int) vous indique si un caractère est un chiffre. Si vous partez du principe de l'ASCII et de la base 10, vous pouvez également utiliser :

int first_non_digit_offset= strspn(string, "0123456789")

5voto

MSalters Points 74024

Dans le même esprit que la réponse de Misha, mais plus correcte : sscanf(buf, "%*u%*c")==1 .

scanf renvoie 0 si le %d l'extraction des chiffres échoue, et 2 s'il y a quelque chose après les chiffres capturés par %c . Et comme * empêche la valeur d'être stockée, vous ne pouvez même pas obtenir un débordement.

4voto

paxdiablo Points 341644

El cctype possède un bon nombre de fonctions de classification des caractères que vous pouvez utiliser sur chaque caractère de la chaîne. Pour les contrôles numériques, ce serait isdigit .

Le programme suivant montre comment vérifier chaque caractère d'une chaîne de caractères C ou C++ (le processus est à peu près identique en termes de vérification des caractères réels, la seule vraie différence étant la façon d'obtenir la longueur) :

#include <iostream>
#include <cstring>
#include <cctype>
int main (void) {
    const char *xyzzy = "42x";
    std::cout << xyzzy << '\n';
    for (int i = 0; i < std::strlen (xyzzy); i++) {
        if (! std::isdigit (xyzzy[i])) {
            std::cout << xyzzy[i] << " is not numeric.\n";
        }
    }

    std::string plugh ("3141y59");
    std::cout << plugh << '\n';
    for (int i = 0; i < plugh.length(); i++) {
        if (! std::isdigit (plugh[i])) {
            std::cout << plugh[i] << " is not numeric.\n";
        }
    }

    return 0;
}

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