Je travaille sur un "bout" de code pour faire une saisie long int et gérer l'erreur de frappe (comme une lettre ou deux ou trois dans la saisie).
pour ça j'ai écrit un petit bout de code TESTEUR (compilable)
1ère idée Envoyer l'utilisateur se faire voir (un peu barbare) ;)
2ème idée un peut plus interessante vérifier que tous les caractères de la chaine sont des chiffres
Ca marche mais il est impossible de traiter l'erreur.
3éme idée et c'est là que je vais avoir besoin de vos conseils/idées
utiliser pour convertir long int = chaine:
P.saisie=stroul(&buffer, NULL, 10)
ceci fonctionne mais ne selectionne que les X chiffres présents avant le caractère génant
par exemple :
si buffer = 1234d555
p.saisie = 1234
et non 1234555 <
ce que je veux faire comme correction automatique justement pour éviter les utilisateurs porteurs de moufles
j'ai fouiller le fichier sting.h pour trouver une fonction capable de supprimer un caractere dans un char buffer[X]; mais je n'ai rien trouvé de tout ça...
Je pense donc qu'il faut créer une fonction
du style
for(i=0;i<strlen(buffer);i++)
{
switch(buffer[i])
{
case '0' :
strcat(buffer2[i],buffer[i]);
break ;
// .... etc ... pour les 10 chiffres
default : // ne rien faire
break;
}
}
en utilisant la fonction strcat.
puis
P.saisie=stroul(&buffer2, NULL, 10)
est ce une bonne méthode ?
y'a t'il plus simple ?
# str what ?
Posté par ecid . Évalué à 2.
N'est-ce pas strtoul que tu veux utiliser ?
Dans ce cas là (juste pour chipoter), tu veux une saisie d'un
unsigned long int
Quand tu dis que la méthode 2 ne te permet pas de traiter l'erreur, tu veux dire gérer errno ?
Si tu vérifies que tous les caractères sont des chiffres et que tu ne dépasses pas ULONG_MAX (auquel cas errno serait positionné à ERANGE par strtoul), qu'est-ce qui t'empêche de faire ça à la main ?
unsigned long resultat=0
unsigned long limite=0
Tant que parcours de la chaine
Si le caractère est compris entre '0' et '9'alors
result *= 10
result += valeur portée par le caractère testé
finsi
si result < limite alors
depassement ERANGE et tout le toutim puis on sort
sinon
limite = result
finsi
fin tant que
# Pas beaucoup plus simple...
Posté par alf . Évalué à 5.
Premier truc, pour ta boucle de copie, la norme C garantit que '1' == '0' + 1, '2' == '0' + 2... (cf. 5.2.1p3 du n1124 : ). Donc tu n'as pas besoin de switch, un if (c >= '0' && c <= '9') est suffisant. Et, encore mieux, isdigit fourni par l'en-tête ctype.h.
Deuxième truc : for(i=0;i<strlen(buffer);i++) Il y a de fortes chances que strlen soit appelée à chaque itération, à moins que le compilo arrive à se prouver que tu ne modifies pas le contenu de buffer à l'intérieur de ta boucle (ce qui n'est pas gagné). Il est mieux de faire : Enfin, pour strtoul, j'ai un doute en voyant tes bouts de code. Le premier paramètre est une chaînes de caractères, donc un char*. Si buffer2 est de ce type, ou un tableau défini par quelque chose comme char buffer2[N], alors le & est une erreur :
[^] # Re: Pas beaucoup plus simple...
Posté par frp31 . Évalué à 1.
je vous remercie
pendant ce temps j'ai aussi vu sur un autre forum une solution utilisant une fonction simple également :
void SupprimeNonChiffre2(char * const szDest, char const * const sczSrc)
{ size_t i,j;
for(i=0,j=0 ; sczSrc[i] != '\0' ; i++ )
{
char c = sczSrc[i];
int ic = (int)(unsigned char)c; /* isdigit() réclame un int */
if(isdigit(ic))
{ szDest[j] = c; j++; }
} szDest[j] = '\0'; }
je vous remercie j'ai compris les deux méthodeje vais donc m'en sortir maintenant.
Merci
[^] # Re: Pas beaucoup plus simple...
Posté par fabien . Évalué à 2.
} szDest[j] = '\0'; }
je ne vois pas pourquoi tu place ton zero terminateur a chaque iteration, et en plus tu le place même quand c'est pas un digit.
alors qu'il suffit de la placer apres ton for()
sinon, ok.
moi perso, j'aime pas ecrire '\0', j'utilise NULL, ou carrement 0, mais ca c'est une question de gout je pense.
[^] # Re: Pas beaucoup plus simple...
Posté par fabien . Évalué à 2.
(en fait j'avais pas vu que l'accolade fermante n'etait pas celle du for mais celle de la definition de fonction.)
désolé.
[^] # Re: Pas beaucoup plus simple...
Posté par alf . Évalué à 2.
La macro NULL peut en effet être définie par 0, auquel cas tu n'as pas de problème, mais aussi par (void *) 0, auquel cas tu fais alors une conversion d'une valeur de type pointeur en un type entier, ce qui est implementation-defined. Peu dangereux en pratique, mais autant utiliser les bons types dès le début.
[^] # Re: Pas beaucoup plus simple...
Posté par ecid . Évalué à 1.
J'ai regardé la macro (qui fait le cast en unsigned char) et le tableau _ctype_ associé (bon c'est sur du OpenBSD, mais j'ai pas de Linux là sous la main). J'ai fait le test suivant:
isdigit(-250) : La réponse est positive.
Comme quoi le test d'un int avec ( >= '0' && <= '9') est quand même différent de isdigit().
[^] # Re: Pas beaucoup plus simple...
Posté par alf . Évalué à 2.
Dixit 7.4p1 :
Donc:
- Si EOF ne vaut pas -250 sur ton implémentation, alors tu viens de tester un comportement indéfini.
- Si EOF vaut -250, alors ton implémentation est buggée.
Je plaide pour la première possibilité (J'ai du mal à croire que la libc d'OpenBSD puisse être aussi buggée pour renvoyer vrai pour EOF) (et j'ai aussi du mal à croire qu'EOF puisse valoir -250, c'est plus probablement -1).
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.