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

Yeah -  
[Dal] Messages postés 6122 Date d'inscription   Statut Contributeur Dernière intervention   -
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

  1. [Dal] Messages postés 6122 Date d'inscription   Statut Contributeur Dernière intervention   1 108
     
    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
    1. Yeah
       
      Merciii beaucoup ??
      0
    2. Yeah
       
      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
    3. [Dal] Messages postés 6122 Date d'inscription   Statut Contributeur Dernière intervention   1 108
       
      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
    4. [Dal] Messages postés 6122 Date d'inscription   Statut Contributeur Dernière intervention   1 108
       
      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
    5. [Dal] Messages postés 6122 Date d'inscription   Statut Contributeur Dernière intervention   1 108
       
      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