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
Alexandre Bacquart
scls19fr wrote:
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
ce qui me gêne c'est que atoi renvoie 0 en cas d'erreur !



Tu n'as pas bien lu ma première réponse. strtol() te permet de savoir si
la chaîne contient bien le nombre. Dans l'exemple, je ne teste pas le
retour, mais le 2ème argument de strtol() (endptr), c'est lui qui te
dira si la chaîne contenait effectivement un nombre. De cette manière,
la fonction strtol() a deux fonctions : convertir une chaîne en valeur,
et vérifier qu'effectivement la conversion s'est bien passée (autrement
dit, que le chaîne contenait bien un nombre).

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



Là, c'était ma 2ème réponse. Convertit en int avec un cast. Si tu as
peur que la valeur soit trop grande, alors teste le retour avec INT_MIN
et INT_MAX.


--
Alex
Avatar
Alexandre Bacquart
Eric Levenez wrote:
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),



Cela ne suffit pas pour le problème évoqué. Dans l'absolu, il doit
tester la valeur de endptr, pas seulement errno.

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.



strtoul() renvoit également 0 en cas d'erreur. C'est le second argument
(endptr) qui permet de vérifier qu'il y avait bien un nombre.

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.



Oui, mais dans ce cas, ce n'est plus standard.

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...



Réinvention de la roue... strtol() fait tout cela.


--
Alex
Avatar
Richard Delorme
Alexandre Bacquart a écrit :

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.



Oui, mais dans ce cas, ce n'est plus standard.



Si : chapitre 4 verset 6 :
A conforming freestanding implementation
shall accept any strictly conforming program that does not use complex
types and in which the use of the features specified in the library
clause (clause 7) is confined to the contents of the standard headers
<float.h>, <iso646.h>, <limits.h>, <stdarg.h>, <stdbool.h>, <stddef.h>,
and <stdint.h>.

<stdlib.h> n'est pas dans la liste.

Réinvention de la roue... strtol() fait tout cela.



Il peut ne pas exister, on ne pas faire ce que l'on souhaite de manière
satisfaisante.

--
Richard
Avatar
scls19fr
Merci à vous tous... effectivement ma question était assez mal posée
(mais c'était volontaire pour qu'elle soit suffisamment "ouverte")

Voilà ce que j'ai fait :

int contain_number(const char * token) {
char ** endptr = NULL;
long int val;
val=strtol(token, endptr, 0);
return !(val==0 && endptr==token);
}

mais ça ne fonctionne pas...

ça renvoie toujours vrai même avec une chaîne contenant du texte !
Avatar
Richard Delorme
scls19fr a écrit :
Merci à vous tous... effectivement ma question était assez mal posée
(mais c'était volontaire pour qu'elle soit suffisamment "ouverte")

Voilà ce que j'ai fait :

int contain_number(const char * token) {
char ** endptr = NULL;
long int val;
val=strtol(token, endptr, 0);
return !(val==0 && endptr==token);
}


return !(val==0 && *endptr==token);

--
Richard
Avatar
scls19fr
>     return !(val==0 && *endptr==token);



C'est balaud ! mais ça me fait un Bus Error quand je met ça !
Avatar
Marc
Richard Delorme wrote:

scls19fr a écrit :
Voilà ce que j'ai fait :

int contain_number(const char * token) {
char ** endptr = NULL;
long int val;
val=strtol(token, endptr, 0);
return !(val==0 && endptr==token);
}


return !(val==0 && *endptr==token);



Je ne suis pas sûr que ça serve à grand chose de tester val==0. Mais ce
n'est pas le problème.

const char* endptr;
... strtol(token, &endptr, 0)
return endptr!=token;

Si strtol voit NULL en second argument, il est très fort s'il devine où
stocker le résultat. Le const en plus, c'est parce que j'aime le C++
(hmm, je viens de jeter un oeil au dernier draft, et ça semble passer
sans le const, ça doit être une erreur).
Avatar
scls19fr
> const char* endptr;
... strtol(token, &endptr, 0)
return endptr!=token;



Merci ça marche...
par contre j'ai un warning à la compilation (je compile avec les flags
-Wall -pedantic )
warning: passing argument 2 of 'strtol' from incompatible pointer type
Une idée pour l'éviter ?
Avatar
Marc
scls19fr wrote:

const char* endptr;
... strtol(token, &endptr, 0)
return endptr!=token;



Merci ça marche...
par contre j'ai un warning à la compilation (je compile avec les flags
-Wall -pedantic )
warning: passing argument 2 of 'strtol' from incompatible pointer type
Une idée pour l'éviter ?



Enlever le const. Malheureusement, on n'a pas le choix... (c'est même une
erreur généralement et pas simplement un warning)

Accessoirement, ça répond à ma question pour le C++ : changer le
prototype serait certes bien, mais ça casserait la compatibilité avec le
C :-(
Avatar
espie
In article <gtjl2a$27g1$, Marc wrote:
scls19fr wrote:

const char* endptr;
... strtol(token, &endptr, 0)
return endptr!=token;



Merci ça marche...
par contre j'ai un warning à la compilation (je compile avec les flags
-Wall -pedantic )
warning: passing argument 2 of 'strtol' from incompatible pointer type
Une idée pour l'éviter ?



Enlever le const. Malheureusement, on n'a pas le choix... (c'est même une
erreur généralement et pas simplement un warning)

Accessoirement, ça répond à ma question pour le C++ : changer le
prototype serait certes bien, mais ça casserait la compatibilité avec le
C :-(



euh non, ca serait mal.

Il y a une vraie raison pour laquelle il n'y a pas de const, c'est que
tu ne sais pas si ton premier parametre est "vraiment" const ou pas, et
que le resultat doit y etre lie.

Je ne pense pas que tu puisses t'en sortir simplement mieux en C++...
Tu pourrais essayer d'avoir plusieurs surcharges de ta fonction, mais
j'ai l'impression que ca marchera aussi bien que d'essayer de surcharger
operator[] pour distinguer les acces en lecture des acces en ecriture
(e.g., tres mal sans rajouter plein d'objets intermediaires).
1 2 3