Langage C Problème avec Boucle While et getchar();

Fermé
Yeah - 15 nov. 2013 à 13:59
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 15 nov. 2013 à 16:14
Bonjour,


j'ai écris un programme, qui initialise un Tableau , après un msg qui demande si on veut boucler ou non , le problème c'est quand je saisie 'O' pour refaire les instructions le programme ne boucle pas !

void Init(groupe *gr11)
{
char rep;
gr11->dim=0;
printf("Veuillez Entrer le nom de Groupe\n");
scanf("%s", &gr11->nom);
do{
printf("Entrez la note\n");
scanf("%f", &gr11->note[gr11->dim]);
gr11->dim++;
printf("Encore O/N\n");
rep=getchar();
}while(rep=='O');
}

1 réponse

[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié par [Dal] le 15/11/2013 à 15:10
Salut Yeah,

Cela vient du fait qu'après avoir fait tes scanf, tu ne te préoccupes pas de vider le flux stdin, qui, au stade de ton getchar() dans la boucle contient au moins le retour chariot
'\n'
provenant du précédent scanf sinon plus.

Pour t'en convaincre, lorsque le programme demande "Veuillez Entrer le nom de Groupe", tape ceci :
toto 12.34N
et valide (presse enter).

Qu'arrive-t-il ? Le flux stdin contient
toto 12.34N\n
.

C'est plus qu'il n'en faut à ton programme, qui ne prend pas la peine de s'arrêter pour demander les autres entrées à l'utilisateur, il prend "toto" comme %s, puis 12.34 comme %f, puis 'N' pour ton getchar et se termine.

Donc, comme tu le vois, scanf et getch, qui sollicitent le flux stdin, se contentent de piocher dans le flux stdin les caractères qui y restent.

Pour purger stdin après chaque scanf, ajoute ceci :

while ((c = getchar()) != '\n' && c != EOF)

/* vidage de stdin */ ;

avec c définit comme
char c;
.

C'est la façon habituelle de procéder en C pour purger stdin.


Dal
1
Merciii beaucoup ??
0
Pouvez vous m'expliquer pourquoi dans cet exemple suivant on n'a pas besoin de puger le stdin afin de prendre la 2eme valeur

void main()
{
char c[4];
float l;
printf("Entrez");
scanf("%s", &c);
printf("et float");
scanf("%f", &l);
printf("%s %f", c,l);
getch();
}
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
15 nov. 2013 à 15:52
La purge est utile dans ce cas aussi.

Au premier scanf tape "toto 12a".

Ce ne sont pas les seuls problèmes dans ton code, car lorsque tu fais
scanf("%s", &gr11->nom); 
pour demander un "nom de groupe", ou
scanf("%s", &c);
comme dans ton dernier code ci-dessus, tu ne vérifies pas que l'entrée ne dépasse pas la capacité de mémoire réservée pour
gr11->nom
ou pour
char c[4];
.

De plus, comme
gr11->nom
devrait être une chaîne (cependant on n'a pas le détail de ton type), c'est en tout cas le cas de
char c[4];
, c'est en fait déjà un pointeur sur char. Par conséquent, tu ne devrais pas le préfixer de "&".


Dal
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié par [Dal] le 15/11/2013 à 16:05
Oups... je viens de réaliser que tu utilises "getch()" et non "getchar()".

getch n'est pas une fonction standard du C. Je suppose que tu es allé la chercher dans un conio.h (ou ailleurs ?).

Selon l'implémentation de cette fonction, le terminal va se comporter différemment, et pourra ne pas prendre en compte le flux stdin préexistant pour passer le terminal dans un mode où on attend la pression d'une touche sans écho à l'écran.

Ce n'est pas du C standard, donc c'est à éviter si tu veux faire du code portable.


Dal
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
15 nov. 2013 à 16:14
Par exemple, j'ai testé ceci :

#include <stdio.h>

#include <stdlib.h>
#include <conio.h>

int main(void)
{
char c[4];
float l;
printf("Entrez\n");
scanf("%s", c);
printf("et float\n");
scanf("%f", &l);
printf("%s %f", c, l);
getch();
printf("attente 1\n"); getchar();
printf("attente 2\n"); getchar();
printf("attente 3\n"); getchar();

return 0;
}

en tapant "toto 12abc" au premier scanf.

Chez moi (compilé avec MinGW) la lecture du flux stdin est juste suspendue au getch(), et reprend, non purgée après, le programme ne s'arrêtant pas aux getchar() qui sont à la suite.


Dal
0