Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Tester si une chaîne contient un nombre

26 réponses
Avatar
noone
Bonjour,

je souhaite tester si une cha=EEne (char *) contient un nombre.
Existe-t'il une fonction standard dans la libc pour =E7a ?
J'ai vu int isdigit( int ch ) mais c'est juste pour tester si un char
est un chiffre...
J'ai aussi vu int isdigit( int ch );
Une id=E9e ?
Est-ce qu'utiliser une regexp en est une bonne ?

Merci d'avance

10 réponses

1 2 3
Avatar
Eric Levenez
Le 02/05/09 19:08, dans
,
«  » a écrit :

je souhaite tester si une chaîne (char *) contient un nombre.



Il faudrait savoir quel type de nombre : entier, flottant, hexadécimal,
signé, non signé...

Existe-t'il une fonction standard dans la libc pour ça ?



Tu peux utiliser la fonction de conversion associée : strtol, strtod,
strtold, strtoll, strtoul, strtoull...

Il faut tester le "char ** restrict endptr" pour voir où s'est arrêté la
conversion et errno pour les erreurs.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
scls19fr
> Il faudrait savoir quel type de nombre : entier, flottant, hexadécimal,
signé, non signé...



Disons dans un premier temps un entier non signé
(ensuite on pourra parler d'un flottant écrit ou pas avec "E")

Tu peux utiliser la fonction de conversion associée : strtol, strtod,
strtold, strtoll, strtoul, strtoull...



je connais aussi atoi atof ...

Il faut tester le "char ** restrict endptr" pour voir où s'est arrêt é la
conversion et errno pour les erreurs.



???
désolé je n'ai pas compris

Ce qui me gêne avec atoi par exemple c'est qu'elle renvoie 0 si
il y a un pb... or on peut aussi explicitement mettre 0 dans la chaîne
à convertir...
Avatar
Eric Levenez
Le 02/05/09 19:57, dans
,
« scls19fr » a écrit :

Il faudrait savoir quel type de nombre : entier, flottant, hexadécimal,
signé, non signé...



Disons dans un premier temps un entier non signé
(ensuite on pourra parler d'un flottant écrit ou pas avec "E")

Tu peux utiliser la fonction de conversion associée : strtol, strtod,
strtold, strtoll, strtoul, strtoull...



je connais aussi atoi atof ...



atoi et atof ne permettent pas de tester la fin de chaîne comme strto*.

Il faut tester le "char ** restrict endptr" pour voir où s'est arrêté la
conversion et errno pour les erreurs.



???
désolé je n'ai pas compris



Le deuxième argument de strtol (par exemple), permet de savoir où la
conversion s'est arrêté. Si toute la chaîne a été traitée par strtol, q doit
pointer sur le caractère nul de fin de chaîne, sinon un caractère parasite à
arrêté la conversion.

p = "123toto";
n = strtoul(p, q, 10);
if (*q)
printf("Fin: %sn", q);

Le code suivant va afficher "Fin: toto". Après, il reste à définir dans des
spécifications, si cela correspond ou non à une erreur.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
scls19fr
Merci

mais ce qui me gêne c'est que moi je veux faire une conversion vers un
int pas vers un long int !

et faire la conversion vers un long int juste pour détecter l'erreur
éventuelle puis faire un cast après vers un int
... ça me semble un peu discutable ... non ?
Avatar
Alexandre Bacquart
wrote:
Bonjour,

je souhaite tester si une chaîne (char *) contient un nombre.
Existe-t'il une fonction standard dans la libc pour ça ?



char *s;
char *endptr;

/* ... */

long n = strtol(s, &endptr, 10);
if (endptr == s) {
/* s ne représente pas un nombre base 10 */
} else {
/* n = le nombre base 10 représenté par s */
}

strtol() convertit une chaîne en nombre. Ca ne marche que si la chaîne
*commence* par un nombre, pas si elle contient un nombre quelque-part :
la chaîne "z 234 y" ne retournera pas 234, mais " 234 y" oui, car les
espaces (selon isspace()) sont ignorés.

Si la chaîne ne représente pas un nombre, 0 est retourné et le deuxième
argument sera égal au pointeur de la chaîne. Si le nombre ne rentre pas
dans un long, errno == ERANGE.

atol() est plus simple, mais tu ne sauras pas si la conversion a eu
lieu, puisqu'elle retourne simplement 0 en cas de problème (de plus,
aucune garantie que errno soit positionné en cas de débordement).

J'ai vu int isdigit( int ch ) mais c'est juste pour tester si un char
est un chiffre...
J'ai aussi vu int isdigit( int ch );
Une idée ?
Est-ce qu'utiliser une regexp en est une bonne ?



Les regexp ne sont pas normalisées en C. Mais si tu as accès aux regexp,
pour une représentation décimale simple, quelque-chose comme :

"[0-9]+.?[0-9]*"

Et pour un entier :

"[0-9]+"

...devraient faire l'affaire. Mais à ne pas confondre avec strtol() et
ses copains, qui sont bien plus complexes (leur recherche de nombre est
plus proche de la syntaxe des constantes nombre de C).


--
Alex
Avatar
Alexandre Bacquart
scls19fr wrote:
Merci

mais ce qui me gêne c'est que moi je veux faire une conversion vers un
int pas vers un long int !



Il vaut mieux avoir une fonction qui fait ce travail sur un long qu'une
fonction qui le fait sur un int, tu ne crois pas ?

et faire la conversion vers un long int juste pour détecter l'erreur
éventuelle puis faire un cast après vers un int



Tu n'as pas parlé de convertir la chaîne en nombre, mais de vérifier si
la chaîne contient bien un nombre. A ma connaissance, il n'y a pas de
telle fonction dans la bibliothèque standard.

... ça me semble un peu discutable ... non ?



A toi de tester si le long retourné est convertible en int si tu penses
que la chaîne est susceptible de contenir un nombre > INT_MAX ou < INT_MIN.


--
Alex
Avatar
scls19fr
> Tu n'as pas parlé de convertir la chaîne en nombre, mais de vérifie r si
la chaîne contient bien un nombre. A ma connaissance, il n'y a pas de
telle fonction dans la bibliothèque standard.



En fait je veux faire les deux... d'abord tester si la chaine contient
bien un nombre
(et uniquement un nombre) (c'est pour un petit parseur)

ensuite, si la chaine contient bien un nombre je fais la conversion en
int avec atoi
ce qui me gêne c'est que atoi renvoie 0 en cas d'erreur !

je préfère ne pas trop utiliser de variable trop grande car c'est pour
un microcontrôleur
Avatar
Eric Levenez
Le 02/05/09 21:55, dans
,
« scls19fr » a écrit :

Tu n'as pas parlé de convertir la chaîne en nombre, mais de vérifier si
la chaîne contient bien un nombre. A ma connaissance, il n'y a pas de
telle fonction dans la bibliothèque standard.



En fait je veux faire les deux... d'abord tester si la chaine contient
bien un nombre
(et uniquement un nombre) (c'est pour un petit parseur)

ensuite, si la chaine contient bien un nombre je fais la conversion en
int avec atoi



Premièrement il faut utiliser strtol et pas atoi pour tester si la chaîne
est acceptable ou non.

Deuxièmement autant utiliser une fonction qui fait tout en une fois que
d'appeler 2 fonctions.

Comme le long peut contenir un nombre plus grand ou égal à un int, autant
faire la conversion en long et si celle-ci se passe bien (pas de errno à
ERANGE), tu peux regarder si le long est entre INT_MIN et INT_MAX avant de
le mettre dans un int.

ce qui me gêne c'est que atoi renvoie 0 en cas d'erreur !



Vu que tu n'as pas à utiliser atoi, il n'y a pas de problème.

je préfère ne pas trop utiliser de variable trop grande car c'est pour
un microcontrôleur



Dans ce cas tu as toutes les chances d'avoir un sous ensemble de la
bibliothèque C avec de nombreuses restrictions. Il faut que tu regardes dans
ta doc pour voir ce qu'il en est.

Si donc tu veux un contrôle plus fin de ta chaîne, autant coder toi même la
routine en 3 ou 4 lignes en bouclant simplement sur ta chaîne et tant qu'il
y a un chiffre tu décales de 10 ton nombre et tu ajoutes le chiffre. Là tu
peux contrôler tout ce que tu veux, comme la présence de blanc, d'un signe,
d'un débordement...

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
scls19fr
Ok merci à vous deux je pense que je vais me débrouiller
Avatar
espie
In article ,
scls19fr wrote:
Ok merci à vous deux je pense que je vais me débrouiller



Pour une prochaine fois, c'est l'exemple-meme de discussion ou tu as pose
une question mal foutue, ou tu as eu des reponses partielles qui ne
convenaient pas vraiment, pour finalement realiser qu'au bout du compte,
ta question etait mal posee, et que tu aurais les 3/4 de la reponse en
la reformulant correctement.

-> de mon point de vue, le probleme n'est pas un probleme de C, mais un
probleme de methodologie. Globalement, dans enormement de cas, tu vas
tomber sur des problemes ou il faut commencer par formuler completement
le probleme, et ca te donne les 9/10 de la reponse. C'est particulierement
vrai pour les entrees-sorties, comme tu peux le constater. Le probleme du
0 vs. 0 de atoi() n'est que le commencement des emmerdes...
1 2 3