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 ?
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 :-(
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 :-(
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 :-(
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
Le 02/05/2009 18:37, scls19fr <s.celles@gmail.com> é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).
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
-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.
On 2 mai, 19:08, "no...@nowhere.undef" <s.cel...@gmail.com> 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.
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.
-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..
On 2 mai, 20:37, scls19fr <s.cel...@gmail.com> 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..
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..
-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 !