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

6 réponses

1 2 3
Avatar
scls19fr
Ok merci à vous tous...
ça marche nickel
Avatar
Marc
Marc Espie wrote:

[strtol, avec ou sans const]
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).



Tu crois ? La surcharge fonctionne bien, pour strstr et compagnie.

long int strtol(const char *nptr, const char **endptr, int base);
long int strtol(char *nptr, char **endptr, int base);

ça autorise toutes les variantes sauf strtol(const char*,char**,int) qui
est précisément celle qui fait des saletés. Malheureusement, on ne peut
pas écrire de code qui fonctionne à la fois avec le prototype du C et
avec celui que je propose : si le premier argument est const, le
prototype du C impose qu'il n'y ait pas de const, précisément la
construction que j'aurais voulu interdire :-(
Avatar
Antoine Leca
Le 02/05/2009 18:37, scls19fr écrivit :
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 ?



Tu vas rigoler.

Dans la bibliothèque standard, il y a bien une fonction qui fait ce que
veux: elle s'appelle sscanf(), et est super casse-gueule à utiliser
correctement même si elle est effectivement plus souple que strtol().
Pour le problème que tu as fini par exposer (mais en se limitant à des
valeurs en base 10), cela ressemble à
int derriere=0;
if( 1!=sscanf(source, "%d%n", &resultat, &derriere)
|| !derriere || source[derriere] ) c_est_pas_bon();

Seulement ce qui est drôle, c'est que la plupart du temps, sscanf"%d"
appelle strtol(,10) (ou un équivalent interne), et ensuite contraint le
résultat à rentrer dans un int... Autrement dit, il y a quand même une
conversion vers long ; qui plus est, dans la problématique de faire le
plus simple possible, une fonction à tirer-dans-les-coins comme sscanf()
n'est pas DU TOUT adaptée, car toute la souplesse que tu as grâce à la
chaîne de format etc. est compensée par une complexité de
l'implémentation, qui en embarqué signifie tout plein de code en trop et
surtout plein d'espace en pile nécessaire.


Si tu veux réellement gagner un poil à ce niveau, une solution serait de
prendre le code de la fonction strtol() (qui n'est pas compliqué) et de
le réecrire pour en faire Strtoi() qui se limiterait aux int. L'exercice
est intéressant en soi, car il va te montrer que le gain... est
extrêmement limité, peut-être 20 octets d'instruction ! (en comptant
comme gain les tests par rapport à INT_MIN et INT_MAX, mais en ne
comptant pas la taille des éventuelles primitives de calcul sur les
longs induites par strtol(), car dans la pratique elles seront presque
toujours présentes dans ton programme final).


Antoine
Avatar
-ed-
On 2 mai, 19:08, "" wrote:

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



Faire la conversion en binaire avec strtol() ou strtod() et apprendre
à utiliser le 2 ème paramètre... Penser aussi à tester errno. Bien
lire la doc de ces fonctions.
Avatar
-ed-
On 2 mai, 20:37, 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 !



Pas de problèmes. Il suffit de tester la validité avant : >= INT_MIN
et <= INT_MAX.

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 ?



Pas besoin de cast, mais tu peux le mettre si ça calme le
compilateur..
Avatar
-ed-
On 3 mai, 08:19, scls19fr wrote:
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 !



Il faut vraiment lire la doc...

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

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

}

#include <assert.h>

int main (void)
{
assert (contain_number ("0") == 1);
assert (contain_number ("10") == 1);
assert (contain_number ("a") == 0);
assert (contain_number ("10a") == 0);
assert (contain_number ("0x10a") == 1);

return 0;
}
1 2 3