Partage
  • Partager sur Facebook
  • Partager sur Twitter

Un blindage problématique

blindage

    3 janvier 2022 à 18:04:41

    Bonjour à tous.

    Je suis actuellement en train de réaliser un projet de jeu et je m'attarde, après mise en place de beaucoup de fonctionnalités, sur un menu propre et basique : 

     - Il y a 6 choix (de 1 à 6) et pour selectionner la branche d'un menu (jouer, règles, charger une partie..) on doit entrer au clavier son choix (donc avec des scanf)

    Tout semble simple, donc j'ai réalisé un blindage type : - un while qui exclut tout ce qui n'est pas compris entre 1 et 6 inclus ;

                                                                                    - des if qui donnent des instructions pour 1,2,3,4,5,6 ;

    Seulement voilà, tout fonctionne, mais un truc me pose problème.

    Si on tape, lors du menu, "1a" "1b" "1dfjqjzdklqjsdkq" enfin bref tout ce que vous voulez comme chaine de caractères mais qui comporte un des choix entre 1,2,3,4,5,6 ; on accède quand même à la branche 1,2,3,4,5,6 en console. 

    + Déja je voulais savoir si c'est normal et est ce que mon blindage est bon pour cette action

    + Et sinon, ya t'il une possibilité de contourner ce problème et de faire que seul "1", "2", "3".... ect soit accepté dans le scanf ?

    Voici un extrait du programme entier, sur le blindage :

    while (choix < 1 || choix > 6)
         {
            printf("Entrez votre selection : ");
            fflush(stdin);
            scanf("%d", &choix);
         }
    
         switch(choix)
         {
            case 1 :
    
                // Je vous épargne les commandes car ça n'a rien a voir avec le blindage
                break;
    
            case 2 :
                // Je vous épargne les commandes car ça n'a rien a voir avec le blindage
                break;
    
            case 3 :
                // Je vous épargne les commandes car ça n'a rien a voir avec le blindage
                break;
    
            case 4 :
                // Je vous épargne les commandes car ça n'a rien a voir avec le blindage
                break;
    
            case 5 :
               // Je vous épargne les commandes car ça n'a rien a voir avec le blindage
                break;
             case 6 :
               // Je vous épargne les commandes car ça n'a rien a voir avec le blindage
                break;
            }
    }

    Merci aux courageux qui voudront bien m'aider :)

    • Partager sur Facebook
    • Partager sur Twitter
      3 janvier 2022 à 18:17:25

      Le comportement est normal. si tu veux "blinder" plus, tu récupères ta saisie sous forme de chaîne de caractère et tu fais un contrôle de la chaîne pour savoir si tu dois continuez où redemander une nouvelle saisie.
      • Partager sur Facebook
      • Partager sur Twitter
        3 janvier 2022 à 18:20:55

        jamais appris... vous savez comment on fait ça ?

        -
        Edité par Clément 2910 3 janvier 2022 à 18:21:15

        • Partager sur Facebook
        • Partager sur Twitter
          3 janvier 2022 à 18:57:08

          Ton cas est assez simple.
          Utilises  fgets() avec un espace assez long (je suppose que tu ne t'amuseras pas à taper 300 caractères)

          https://koor.fr/C/cstdio/fgets.wp


          Tu regardes le premier et la longueur
          si la longueur n'est pas 1, il y a erreur.

          (il faut enlever le caractère '\n' avant, utilises strlen pour savoir la longueur)
          Si le caractère n'est pas '1', '2', ... c'est une erreur
          tu fais ensuite le calcul  choix = caractere - '0';

          -
          Edité par PierrotLeFou 3 janvier 2022 à 19:06:34

          • Partager sur Facebook
          • Partager sur Twitter

          Le Tout est souvent plus grand que la somme de ses parties.

            3 janvier 2022 à 19:22:30

            ok super merci, et comment on enleve le caractère \n ?
            • Partager sur Facebook
            • Partager sur Twitter
              3 janvier 2022 à 19:25:27

              Hello,

              Clément 2910 a écrit:

              ok super merci, et comment on enleve le caractère \n ?


              Comme ceci par exemple

              char str[....];
              fgets(str,sizeof(str),stdin);
              char *p=strchr(str,'\n');
              if(p)
                  *p=0;





              -
              Edité par edgarjacobs 3 janvier 2022 à 19:32:36

              • Partager sur Facebook
              • Partager sur Twitter

              Il y a ceux qui font des sauvegardes, et ceux qui n'ont pas encore eu d'incident....

                3 janvier 2022 à 19:32:14

                En fait j'ai l'impression que si je veux que ça marche, il ne faut pas que j'utilise "switch"... car on me renvoie l'erreur comme quoi switch n'accepte que les integer....
                • Partager sur Facebook
                • Partager sur Twitter
                  3 janvier 2022 à 19:37:03

                  Clément 2910 a écrit:

                  En fait j'ai l'impression que si je veux que ça marche, il ne faut pas que j'utilise "switch"... car on me renvoie l'erreur comme quoi switch n'accepte que les integer....

                  Sur quoi essaies-tu de faire un swirch?
                  PierrotLeFou t'as indiqué la méthode à suivre, qu'as-tu fait?
                  • Partager sur Facebook
                  • Partager sur Twitter

                  En recherche d'emploi.

                    3 janvier 2022 à 19:39:20

                    Evidemment. Si tu as écrit

                    char str[....];
                    fgets(str,....)
                    switch(str) {

                    ça ne va pas être possible. Par contre, écrire

                    char str[....];
                    fgets(str,....);
                    switch(*str-'0') {    // ou str[0]-'0'
                        case 1:
                        case 2:
                    ....

                    ça va être ok.

                    *str-'0', ça fait quoi ? Ça prend le premier caractère de str ('1', '2', etc) et lui retire la valeur du caractère '0'. Donc, '1'-'0', c'est (en ascii) 49-48, soit 1. Bingo.

                    Et tu peux aussi écrire (écriture que je préfère)

                    switch(*str) {
                    	case '1': 
                    	case '2':
                    ....





                    -
                    Edité par edgarjacobs 3 janvier 2022 à 19:46:42

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Il y a ceux qui font des sauvegardes, et ceux qui n'ont pas encore eu d'incident....

                      3 janvier 2022 à 19:54:06

                      bah ça fonctionne mais mon programme crashe dès que j'entre une séléction... je comprend pas vraiment d'où ça vient (alors qu'avec le blindage simple marchait bien entendu) :

                      while (strlen(choix) != 1 && choix != 1 && choix != 2 && choix != 3 && choix != 4 && choix != 5 && choix != 6)
                           {
                              system("cls");
                              affichage_choix();
                              gotoligcol(16,70);
                              printf("Entrez votre selection : ");
                              fflush(stdin);
                              fgets(choix,sizeof(choix),stdin);
                              char *p=strchr(choix,'\n');
                              if(p)
                                  *p=0;
                      
                           }
                           system("cls");
                      
                           switch(*choix-'0')
                           {
                              case 1 :
                      
                                  // Bloc d'instruction...
                                  // Case 2 case 3 ... ect 



                      • Partager sur Facebook
                      • Partager sur Twitter
                        3 janvier 2022 à 19:57:52

                        Heuuu.... tu as dû avoir une pelletée de warning pour ta ligne 1. Tu compares une adresse (choix est un pointeur) avec un entier....

                        Et on ne fflush() pas stdin, cela peut avoir un comportement indéterminé, voir ici.

                        -
                        Edité par edgarjacobs 3 janvier 2022 à 20:02:12

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Il y a ceux qui font des sauvegardes, et ceux qui n'ont pas encore eu d'incident....

                          3 janvier 2022 à 20:01:38

                          Il s'agit d'un programme qui

                          • pose des questions
                          • attend une reponse. L'utilisateur tape quelque chose puis [Entrée]
                          Ca fonctionne donc par _lignes_.
                          Pour blinder, le plus simple c'est
                          • de lire une ligne complète dans une chaine (fgets, getline....)
                          • de décoder la ligne  (sscanf).
                          Par exemple, pour lire un entier et s'assurer qu'il n'y a rien d'autre derrière

                          // lire la ligne
                          
                          char ligne[1000];
                          fgets(ligne, 1000, stdin;
                          
                          // essayer de lire un nombre + un caractère
                          
                          int nombre;
                          char ch;
                          
                          int r = sscanf(ligne, "%s%c", &nombre, &ch);
                          
                          si r vaut 1 c'est bon, il a réussi a lire le nombre et rien d'autre.
                          Si c'est 0, le nombre n'était pas valide
                          Si c'est 2, il était suivi d'une merdouille sur la ligne.


                          -
                          Edité par michelbillaud 3 janvier 2022 à 20:02:31

                          • Partager sur Facebook
                          • Partager sur Twitter
                            3 janvier 2022 à 20:06:43

                            @michelbillaud: ligne 11: plutôt %d que %s

                            -
                            Edité par edgarjacobs 3 janvier 2022 à 20:08:42

                            • Partager sur Facebook
                            • Partager sur Twitter

                            Il y a ceux qui font des sauvegardes, et ceux qui n'ont pas encore eu d'incident....

                              3 janvier 2022 à 20:15:06

                              Merci les gars, j'ai réussi, tout marche bien et j'ai supprimé les warnings sur la ligne.

                              Je laisse ouvert pendant quelques heures si j'ai de nouveau, un pb, mais sinon merci bcp :D !

                              • Partager sur Facebook
                              • Partager sur Twitter
                                3 janvier 2022 à 20:24:10

                                Tant mieux. Et si tu postais ton dernier code, qu'on y jette un coup d'oeil ?
                                • Partager sur Facebook
                                • Partager sur Twitter

                                Il y a ceux qui font des sauvegardes, et ceux qui n'ont pas encore eu d'incident....

                                  3 janvier 2022 à 21:26:06

                                   gotoligcol(16,70);
                                      printf("Entrez votre selection : ");
                                      fgets(choix,sizeof(choix),stdin);
                                      char *p=strchr(choix,'\n');
                                      if(p)
                                          *p=0;
                                  
                                       while (strlen(choix) != 1 && *choix != 1 && *choix != 2 && *choix != 3 && *choix != 4 && *choix != 5 && *choix != 6)
                                       {
                                          system("cls");
                                          affichage_choix();
                                          gotoligcol(16,70);
                                          printf("Entrez votre selection : ");
                                          fgets(choix,sizeof(choix),stdin);
                                          char *p=strchr(choix,'\n');
                                          if(p)
                                              *p=0;
                                  
                                       }
                                       system("cls");
                                  
                                       switch(*choix-'0')
                                       {
                                          case 1 :
                                  
                                              system("cls");
                                              fflush(stdin);
                                              system("cls");
                                              partie_en_cours(repere);
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Un blindage problématique

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  • Editeur
                                  • Markdown