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* ?
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* ?
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
}
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 queunsigned char
ou est égale à la valeur de la macroEOF
. 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.
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.
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 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.