Partage
  • Partager sur Facebook
  • Partager sur Twitter

Pb avec la recuperation de caractere

scanf, getchar, gets et fgets...

Sujet résolu
    17 août 2006 à 16:57:10

    Bonjour à tous.
    En attendant la suite du tuto de M@teo21, je lis, relis et re-relis ce qu'il a deja fait. Bien entendu, je fais, refais et re-refais les TPs (ainsi que les variantes pis comme je suis un gourmand, j'en rajoute! ;) )
    A ma grande satisfaction, ça finit par rentrer dans ma petite tête, et je me rends bien compte que la maniere d'ecrire s'ameliore au fur et a mesure des exercices! (100 fois sur le metier, remets ton ouvrage, petit scarabée :p )
    Seulement, je suis tombé sur un os là. J'ai beau tourner et retourner le probleme dans tous les sens, je suis face à un mur! o_O

    Voici le code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>

    const int MAX=100, MIN=1;
    int nombreMystere=0;

    //Protos
    void saisie();
    void joue();
    int rejoue();


    int main()
    {
        joue();
        rejoue();
    }

    void saisie()//Recuperation et traitement.
    {
        int nombreDeCoups=0, reponse=0;//Declaration et initialisation des vars
        do
        {
            scanf("%d",&reponse);//Recuperation de la reponse
            nombreDeCoups++;//Incrementation du compteur
            if (reponse > nombreMystere)
            printf("Le nombre Mystere est inferieur a %d\\n",reponse);//Trop petit!
            else if (reponse < nombreMystere)
            printf("Le nombre mystere est superieur a %d\\n",reponse);//Trop grand!
        }
        while (reponse!=nombreMystere);//On boucle tant que le nombre n'est pas devine

        printf("\\nVous avez gagne! Le nombre mystere est %d\\n",reponse);//Bravo! C'est gagné

        if (nombreDeCoups==1)//Affichage du nombre de coups
            printf("Il vous a fallut %d coup pour trouver.\\n\\n\\n",nombreDeCoups);
        else
            printf("Il vous a fallut %d coup(s) pour trouver.\\n\\n\\n",nombreDeCoups);
    }

    void joue()//On demarre le jeu!
    {
        nombreMystere = (rand() % (MAX - MIN + 1)) + MIN;//Calcul d'un nombre aleatoire
        printf("*****Le nombre mystere est : %d\\n",nombreMystere);//DEBUG On affiche le nombre genere
        printf("\\nQuelle est votre proposition?\\n");//Prompt

        saisie();//Recuperation et traitement
    }

    int  rejoue()//Voulez vous rejouer?
    {
        char lettre=0;
        printf("Voulez vous jouer une autre partie? (O/N)\\n");
        scanf("%c", &lettre);// Recuperation de la reponse (methode1)
        printf("*****La reponse saisie est : %c\\n",lettre);//Verification de la saisie

        if (lettre=='O'|| lettre=='o')// Si c'est oui
            {
                printf("\\n\\nOn rejoue!!!\\n");
                joue();
            }
            else if (lettre=='N' || lettre=='n')//Si c'est non
            {
                printf ("\\n\\nAu revoir!");
                return 0;
            }
            else//Si l'entrée ne correspond pas a ce qu'on attend
            printf("\\n\\nMerci de taper \\"O\\" pour rejouer ou \\"N\\" pour quitter...\\n");
            rejoue();//On recommence
    }


    Bon, il me semble que j'ai vu passer des messages concernant des soucis avec scanf sur le forum (comment faire une recherche sur le forum? :euh: ), j'ai donc décidé de changer la fonction rejoue() afin d'essayer avec getchar, gets ou mieux encore, fgets, mais mon probleme persiste! :(

    Pour info, voici la fonction rejoue() avec fgets:
    int  rejoue()//Voulez vous rejouer?
    {
        char lettre[2]={0,0};
        printf("Voulez vous jouer une autre partie? (O/N)\\n");
        fgets(lettre,2,stdin);
        printf("*****La reponse saisie est : %s\\n",lettre);//Verification de la saisie

        if (lettre[0]=='O'|| lettre[0]=='o')// Si c'est oui
            {
                printf("\\n\\nOn rejoue!!!\\n");
                joue();
            }
            else if (lettre[0]=='N' || lettre[0]=='n')//Si c'est non
            {
                printf ("\\n\\nAu revoir!");
                return 0;
            }
            else//Si l'entrée ne correspond pas a ce qu'on attend
            printf("\\n\\nMerci de taper \\"O\\" pour rejouer ou \\"N\\" pour quitter...\\n");
            rejoue();//On recommence
    }


    Question subsidiaire:
    Est-il possible d'utiliser une fonction void avec un "return 0" pour la quitter. En clair, ma fonction rejoue doit elle être une void ou une int puisque j'utilise un return 0 afin de quitter le programme?

    Merci de votre aide.
    • Partager sur Facebook
    • Partager sur Twitter
      17 août 2006 à 17:09:38

      Il faut vider le buffer (si tu entres plus de caractères que la taille de la chaine, fgets laisse les caractères en trop dans le buffer (stdin en l'occurence).

      Il faut supprimer aussi le \n (retour à la ligne) de la chaine de caractères sinon tu ne peux pas comparer.

      Voici la fonction qui permet de faire cela :
      static void clean(const char *buffer, FILE *fp)
      {
          char *p = strchr(buffer,'n');
          if (p != NULL)
          {
              *p = 0;
          }
          else
          {
              int c;
              while ((c = fgetc(fp)) != 'n' && c != EOF)
              {
              }
          }
      }


      Utilise ça après fgets comme ceci :
      fgets(chaine, sizeof chaine, stdin);
      clean(chaine, stdin);


      A+
      Kr00pS
      • Partager sur Facebook
      • Partager sur Twitter
        17 août 2006 à 17:23:23

        Merci de ta reponse, je vais essayer sans grande conviction car je crains que ce ne soit pas le cas ici... Si tu compiles ce code et que tu l'execute, tu verras que la fonction rejoue() est executée deux fois pour une raison que je ne m'explique pas. Ceci, sans aucune entrée de la part de l'utilisateur. o_O

        Edit: J'ai essayé avec la fonction clean, et j'ai le même resultat :(
        Faut dire que avec mon tableau, il me semble que je m'affranchis du probleme de "\n".
        Toujours besoin de 2 passages pour pouvoir recuperer la reponse *doh*
        • Partager sur Facebook
        • Partager sur Twitter
          17 août 2006 à 17:42:34

          Il faut vider le buffer. ;)
          • Partager sur Facebook
          • Partager sur Twitter
            17 août 2006 à 18:23:14

            C'est bien ça, mais bon, j'ai galéré pour trouver la fonction. :-°
            Donc, comme je me suis occupé du "\\n" en créant un tableau et n'exploitant que la premiere case, j'ai juste besoin de faire un fflush(stdin) juste avant de faire mon fgets, et tout marche nickel! :p

            Voici le code de la fonction:
            int  rejoue()//Voulez vous rejouer?
            {
                char lettre[2]={0,0};
                printf("Voulez vous jouer une autre partie? (O/N)\\n");
                fflush(stdin);//On vide le buffer stdin (clavier)
                fgets(lettre,2,stdin);//On recupere l'entree au clavier
                printf("*****La reponse saisie est : %s\\n",lettre);//On verifie ce que l'on a recupere
                if (lettre[0]=='O'|| lettre[0]=='o')// Si c'est oui
                    {
                        printf("\\n\\nOn rejoue!!!\\n");
                        joue();
                    }
                    else if (lettre[0]=='N' || lettre[0]=='n')//Si c'est non
                    {
                        printf ("\\n\\nAu revoir!");
                        return 0;
                    }
                    else//Si l'entrée ne correspond pas a ce qu'on attend
                    printf("\\n\\nMerci de taper \\"O\\" pour rejouer ou \\"N\\" pour quitter...\\n");
                    rejoue();//On recommence
            }

            Merci de m'avoir mis sur la piste.

            En ce qui concerne les fonctions dont on ne veut rien recuperer (void) peut on en sortir avec un 'return 0' ou faut il faire une fonction int?
            • Partager sur Facebook
            • Partager sur Twitter
              17 août 2006 à 18:26:37

              Il faut faire une fonction int comme tu dit. Puisque void ne retourne rien tu ne paux pas faire return 0.
              • Partager sur Facebook
              • Partager sur Twitter
                17 août 2006 à 18:37:29

                Ok, merci, je voulais juste en être certain dans la mesure ou les deux fonctionnent. ;)
                • Partager sur Facebook
                • Partager sur Twitter
                  17 août 2006 à 18:52:51

                  fflush(stdin); apporte un comportement indéfini à ton programme, tout peut se passer.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 août 2006 à 21:25:52

                    Comment vider le buffer si la fonction qui le fait rend le programme instable? :o
                    • Partager sur Facebook
                    • Partager sur Twitter
                      17 août 2006 à 21:26:56

                      Pourquoi utilises tu un fgets pour saisir une seule lettre ? Utilise un getchar(); non
                      • Partager sur Facebook
                      • Partager sur Twitter
                        18 août 2006 à 12:38:35

                        Citation : Kr00pS

                        fflush(stdin); apporte un comportement indéfini à ton programme, tout peut se passer.



                        Apres quelques recherches, il semblerait que tu aies raison. Il aurait été constaté que la portabilité de fflush(stdin) n'etait pas excellente: fonctionne sous Windoze, mais pas sous linux pour les flux entrants. o_O
                        Mon probleme restait donc entier car je devais absolument vider ce buffer...

                        De plus, il est dit que la norme n'indiquant le fonctionnement de fflush que sur des flux sortant, cette méthode n'est pas standard et peut conduire à des résultats indéfinis, il convient donc de l'éviter. :-°

                        Une bonne methode afin de realiser un nettoyage du buffer est donc:

                        #include <stdio.h>

                        int c;
                        while ((c = getchar()) != '\\n' && c != EOF); /* mange le tampon */


                        Rendons à César ce qui lui appartient: voici la source.

                        J'ai aussi decouvert les fonctions getch() et getche() qui font exactement ce que je recherchais pour ma fonction rejoue();
                        • Partager sur Facebook
                        • Partager sur Twitter
                          18 août 2006 à 13:02:48

                          Citation : TiTophe


                          J'ai aussi decouvert les fonctions getch() et getche() qui font exactement ce que je recherchais pour ma fonction rejoue();

                          getch () et getche () ne sont pas standard.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            18 août 2006 à 13:07:26

                            Elles font partie de la lib conio.h si c'est ce que tu veux dire.
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Pb avec la recuperation de caractere

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                            • Editeur
                            • Markdown