Forum Programmation.c problème avec la boucle do while

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
-1
13
fév.
2020

bonjour!

je voudrai comprendre pourquoi avec la fonction "gets" ma boucle "do while" ne fonctionne pas correctement, quand j'ai besoin de réessayer l'authentification, la boucle do while passe directement à la demande du mot de passe alors que ca devrait d’abord d’après la structure du code commencer par la demande du login! comment faire
merci!

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

int main()
{
    char login[10];
    char mot[8], cg;
    int i;
    int rep;

    do{ printf("enter le login\n");
      gets(login);

     printf("enter le password\n");
     for(i=0;i<5;i++){
        cg = getch();
        mot[i]=cg;
        cg='*';
        printf("%c",cg);

     }
  mot[i]='\0';
    printf("non:0 ou oui:1");
          scanf("%d",&rep);
    }while(rep==1);

    return 0;
}
  • # Première chose à faire

    Posté par  . Évalué à 1. Dernière modification le 13 février 2020 à 07:37.

    Édite ton post pour ajouter les ``` avant et après le code, parce que là, c'est illisible.

    • [^] # Re: Première chose à faire

      Posté par  (Mastodon) . Évalué à 2.

      fait :)

      En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

      • [^] # Re: Première chose à faire

        Posté par  . Évalué à 1.

        Je le vois toujours dégueulasse, le code de son post, t'es sûr que t'as validé ?

        • [^] # Re: Première chose à faire

          Posté par  (Mastodon) . Évalué à 2.

          curieux il me semblait bien l'avoir fait… là c'est sur c'est fait :)

          En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

  • # stdio.h

    Posté par  (site web personnel) . Évalué à 2.

    Bonjour,

    en tout cas, ça marche avec gets(login); et cg = getchar(); de <stdio.h>.

    Mais j'obtiens :

    gcc essai.c -Wall -Wextra -pedantic -std=c99
    essai.c: In function ‘main’:
    essai.c:14:7: warning: ‘gets’ is deprecated [-Wdeprecated-declarations]
       14 |       gets(login);
          |       ^~~~
    In file included from essai.c:1:
    /usr/include/stdio.h:577:14: note: declared here
      577 | extern char *gets (char *__s) __wur __attribute_deprecated__;
          |              ^~~~
    

    et on peut lire dans stdio.h :

    This function is impossible to use safely. It has been officially
    removed from ISO C11 and ISO C++14, and we have also removed it
    from the _GNU_SOURCE feature list. It remains available when
    explicitly using an old ISO C, Unix, or POSIX standard.

    Je n'ai pas conio.h, qui ne fait pas partie de la librairie standard (https://en.wikipedia.org/wiki/Conio.h).

  • # Un test…

    Posté par  (site web personnel) . Évalué à 2.

    Une supposition: que getch() fournisse la touche appuyée mais ne vide pas le buffer stdin.

    Essaie d'afficher ton login juste après la saisie, histoire de voir ce qui a été «entré» quand tu es repassé dessus en 2ème test.

    Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

    • [^] # Re: Un test…

      Posté par  . Évalué à 0.

      je peut voir ton code stp!

      • [^] # Re: Un test…

        Posté par  . Évalué à 1.

        Ce que te suggère lolop, c'est d'afficher le contenu du login après la saisie, simplement pour voir s'il contient bien ce que tu veux.
        printf("%s\n", login);, quoi.

      • [^] # Re: Un test…

        Posté par  (site web personnel) . Évalué à 2.

        je peut voir ton code stp!

        Non.

        Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

    • [^] # Re: Un test…

      Posté par  . Évalué à 1.

      Ce serait curieux non ? On n'est pas censé passer à la suite tant que gets n'est pas terminé.
      Comment ce serait possible, une optimisation par le compilo ?

      +1 pour le test

      • [^] # Re: Un test…

        Posté par  . Évalué à 0.

        c'est vraiment bizarre cette maniere de lire avec gets! j'essai depuis ca ne fonctionne pas!

        • [^] # Re: Un test…

          Posté par  (site web personnel) . Évalué à 3.

          C'est parce que pour répondre à la question du scanf, vous appuyez sur entrée.

          Cette touche qui n'est pas avalée par le scanf est alors transmise à gets.

          Videz le tampon par un getch(stdin) ou getchar().

          Ensuite, si l'on tape un login de plus de 9 caractères, tout part en vrille.

          #include <termios.h>
          #include <stdio.h>
          #include <stdlib.h>
          
          static struct termios before;
          void initTerm(void)
          {
                  tcgetattr(0, &before);
          }
          void resetTerm(void)
          {
                  tcsetattr(0, TCSANOW, &before);
          }
          
          void setTerm(int echo)
          {
                  struct termios state;
                  tcgetattr(0, &state);
                  state.c_lflag &= ~ICANON;
                  if (echo){
                          state.c_lflag |= ECHO;
                  } else {
                          state.c_lflag &= ~ECHO;
                  }
                  tcsetattr(0, TCSANOW, &state);
          }
          
          int main()
          {
                  char login[10];
                  char mot[8], cg;
                  size_t i;
                  int rep;
          
                  initTerm();
                  do{
                          printf("enter le login:");
          
                          fgets(login,sizeof login,stdin);
                          printf("enter le password:");
                          setTerm(0);
                          for(i=0;i<5;i++){
                                  cg = getchar();
                                  mot[i]=cg;
                                  cg='*';
                                  printf("%c",cg);
                          }
                          setTerm(1);
                          mot[i]='\0';
                          printf("\nnon(0) ou oui(1):");
                          scanf("%d",&rep);
                          getc(stdin);
                  }while(rep==1);
                  resetTerm();
          
                  return 0;
          }

          Si l'on tape des logins trop longs, le buffer stdin va déborder de la même manière sur le getchar du mot de passe.

          • [^] # Re: Un test…

            Posté par  . Évalué à 1.

            merci beaucoup,
            j'ai juste mis getc(stdin); et ça a fonctionné même comme je ne comprend pas ce qui c'est passé.
            besoin d'une petite explication
            merci!

            • [^] # Re: Un test…

              Posté par  (site web personnel) . Évalué à 3. Dernière modification le 13 février 2020 à 12:57.

              Le problème vient de scanf qui ne va pas vider complètement le tampon d'entrée (stdin ).
              Il prend ce qui l'intéresse et va laisser le traîner le retour à la ligne que vous l'utilisateur a envoyé en appuyant sur Entrée.

              Il faut vider proprement le tampon d'entrée après un scanf:

              {
              int c;
              while ((c = getchar()) != '\n' && c != EOF);
              }

              Laisser l'utilisateur taper un login de plus de 9 caractères et vous un problème similaire: le mot de passe va consommer le surplus.

              Enfin, dans mon code. Dans le votre, avec gets -qu'il-ne-faut-pas-utiliser-, vous aurez un dépassement de tampon qui va empiéter sur le code lui-même.

      • [^] # Re: Un test…

        Posté par  (site web personnel) . Évalué à 3. Dernière modification le 13 février 2020 à 11:23.

        Si jamais getch() laisse les données dans le buffer d'entrée (genre il scrute directement le clavier), alors gets() les récupère directement à l'itération suivante… et c'est pas lié au compilo mais bien à getch().

        Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

        • [^] # Re: Un test…

          Posté par  . Évalué à -1.

          ok merci j'ai compris ton hypothèse :)

  • # probleme avec gets

    Posté par  . Évalué à -1. Dernière modification le 13 février 2020 à 11:49.

    //s'il vous plait exécutez ce code et passé au deuxieme test et validans sur "1" vous comprendriez mon probleme!

    #include <stdio.h>
    #include <stdlib.h>
    #include<string.h>
    #include <conio.h>
    
    int main()
    {
        char login[10];
        char mot[8];
        char cg;
        int i;
        int rep;
    
        do{ printf("enter le login\n");
          gets(login);
          printf("%s\n",login);
    
         printf("enter le password\n");
         for(i=0;i<3;i++){
            cg = getch();
            mot[i]=cg;
            cg='*';
            printf("%c",cg);
    
         }
      mot[i]='\0';
      printf("%s\n",mot);
        printf("non:0 ou oui:1");
              scanf("%d",&rep);
        }while(rep==1);
    
        return 0;
    }
    • [^] # Re: probleme avec gets

      Posté par  (site web personnel) . Évalué à 3. Dernière modification le 13 février 2020 à 11:56.

      chepad, quand tu envoies du code, s'il te plaît met le entre ``` comme indiqué dans l'aide mémoire ci-dessous (et même ```c pour avoir la coloration syntaxique). Je viens de le faire pour toi.

      Un LUG en Lorraine : https://enunclic-cappel.fr

      • [^] # Re: probleme avec gets

        Posté par  . Évalué à 1. Dernière modification le 13 février 2020 à 12:06.

        ok j'ai compris et surtout merci à tous mon problème est résolu, même comme je ne comprend par pourquoi j'ai un warning sur mot[i] dans mon code précédant!

        message d'erreur:
        classe\projet_reservation_voillier_version1.0\main.c|64|warning: implicit declaration of function 'getch' [-Wimplicit-function-declaration]|
        ||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|

        • [^] # Re: probleme avec gets

          Posté par  (site web personnel) . Évalué à 4. Dernière modification le 13 février 2020 à 12:47.

          Vous utilisez la bibliothèque conio, un vieux truc pour MS-DOS, sans la donner à l'éditeur de lien.
          (-lconio ou un truc du genre).

          • [^] # Re: probleme avec gets

            Posté par  . Évalué à 3.

            classe\projet_reservation_voillier_version1.0\main.c|64|warning: implicit declaration of function 'getch' [-Wimplicit-function-declaration]|
            ||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|
            

            Ça m'a plutôt l'air d'un avertissement à la compilation, comme si le compilateur n'avait pas trouvé la déclaration de getch alors qu'elle est censée se trouver dans l'en-tête conio.h (pourtant inclus dans le code).

        • [^] # Re: probleme avec gets

          Posté par  (site web personnel) . Évalué à 4.

          j'ai un warning sur mot[i]

          Parce que vous lui donner des valeurs sans jamais l' utiliser ensuite. En bref, il ne sert à rien.

          -Wunused-but-set-variable

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.