Partage
  • Partager sur Facebook
  • Partager sur Twitter

tuto le pendu

conseil

    8 mai 2019 à 5:18:54

    bonjour tout le monde 

    je debute en C et j'aurai aimé des avis sur mon code pour le pendu,savoir s'il est plus ou moins correct ou si je devrais changer des choses,je prend au hasard un mot dans un fichier texte(il y a 30 mots)

    j'ai bien galéré sur la fonction affichage j dois dire car dans le fichier texte les mots etaient les uns en dessous des autres(tenir compte des \n du coup) et le tableau(chaine de '*')avait tjrs un caractere en plus

    ,merci d'avance!

    voici pour la fonction main:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include "jeu.h"
    #define MAX 30 
    #define MIN 0 
    
    
    int main (void)
    {
        signed char motmystere[100]="";
        signed char tableau[100]="";
        signed char lettre=0;
        int taillemot;
        int resultat=0;
       
        int compteur = 1;
    
        srand(time(NULL));
        generemot(motmystere);
        taillemot=strlen(motmystere);
        affichage (motmystere,tableau);
        
    
        
           do
            {
              
                printf("\n\n donnez une lettre\n");
                lettre=lirecaractere();
                comparelettre(lettre,motmystere,tableau,taillemot);
                 printf("\n%s\n",tableau);   
                compteur++;
                if(compteur>10)
                {
                    printf("\ndesole tu as perdu");
                    exit(1);
                }
                resultat=strncmp(tableau,motmystere,strlen(tableau));
     
    
            } while(resultat!=0);
            printf("bravo tu as gagne!!!");
           
    
          
    
        return 0;
    }

    le jeu.c:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "jeu.h"
    #define MAX 30 
    #define MIN 0 
    
    signed char generemot(signed char motmystere[])
    {
        
      int i=(rand()%(MAX-MIN+1)-MIN);
      
      FILE *fichier=NULL;
      fichier=fopen("test.txt","r");
      rewind(fichier);
      int compteurmot=0;
    
      while (compteurmot<=i)
      { 
         fgets(motmystere,100,fichier);
          compteurmot++;
      }
       
        fclose(fichier);
         return *motmystere;
    }
    
    
    void affichage(signed char motmystere[],signed char tableau[])
    {
        int i;
        int j;
        for(i=0;motmystere[i]!='\n';i++)
        {
            
            tableau[i]='*';
        }
        for(j=0;tableau[j]!='\0';j++)
        printf("%c",tableau[j]);
        printf("\n");
    }
    
    
    void comparelettre(signed char lettre,signed char motmystere[],signed char tableau[],int taillemot)
    {
     int i;
     for(i=0;i<=taillemot;i++)
     {
         if(lettre==motmystere[i])
         {
            tableau[i]=lettre;
         }
     }
     
    }
    
    signed char lirecaractere(void)
    { 
        signed char lettre=0;
        lettre=getchar();
        while(getchar()!='\n');
        
        return lettre;
    
    }
    
    
    



    le jeu.h

    #ifndef __jeu__
    #define __jeu__
    
    signed char generemot(signed char motmystere[]);
    void affichage(signed char motmystere[],signed char tableau[]);
    void comparelettre(signed char lettre,signed char motmystere[],signed char tableau [],int taillemot);
    signed char lirecaractere(void);
    
    #endif



    -
    Edité par guth62 8 mai 2019 à 5:36:16

    • Partager sur Facebook
    • Partager sur Twitter
      9 mai 2019 à 14:29:25

      Voyons déjà les warnings que retourne la compilation en -Wall ;)

      jeu.c: In function ‘generemot’:
      jeu.c:20:12: warning: pointer targets in passing argument 1 of ‘fgets’ differ in signedness [-Wpointer-sign]
            fgets(motmystere,100,fichier);
                  ^
      In file included from jeu.c:1:0:
      /usr/include/stdio.h:622:14: note: expected ‘char * __restrict__’ but argument is of type ‘signed char *’
       extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
      

      Tu envoie à fgets un pointeur de char signé alors que fgets prend un pointeur de type char, mais tu lui envoies un "signed char".

      signed char et char ça va donner exactement le même résultat dans ton code - à part si tu as une raison précise de mettre "signed", tu peux virer tous les signed de ton code, ce qui te fera gagner en lisibilité (un programmeur qui voit un mot clef "signed" va se demander : pourquoi avoir mis ce mot clef en particulier ? Il va donc chercher à comprendre si tu as des mécanismes en particulier dans ton code qui utilisent des char négatifs, ce qui n'est pas ton cas).

      De mon côté, quand je corrige tous les signed char, je n'ai plus de warning à la compilation. Bien.

      Maintenant il est temps de tester le programme..

      Segmentation fault
      

      Avec un coup de gdb je trouve que le segfault vient du rewind ligne 15 de jeu.c. Ben oui, forcément, qu'est ce qu'il se passe si ton fichier test.txt n'existe pas ? ;)

      Tu devrais regarder la valeur de retour du fopen, et afficher une erreur si le test.txt n'existe pas.

      Bon, je me créé un test.txt avec quelques mots et je recommence..

      Mon test.txt contient :

      Pomme
      Banane
      Poire
      Chocolat
      

      Le programme a décidé de choisir Chocolat

      ********
      
      
       donnez une lettre
      c
      
      ***c****
      
      
       donnez une lettre
      c
      
      ***c****
      
      
       donnez une lettre
      C
      
      C**c****
      

      Pourquoi quand j'ai rentré c il n'y a que le c du milieu qui s'est affiché ? Parce que tu ne gères pas la casse ;) C'est une amélioration que tu pourrais apporter, de faire en sorte que la casse n'importe pas.

      Enfin, continuons.

      desole tu as perdu

      Déjà ? Tu devrais mettre un compteur et afficher le nombre de coups qui reste ;) Sinon, comment je sais si je suis en train de perdre ?

      Continuons..

      ********
      
      
       donnez une lettre
      z
      
      ********
      
      
       donnez une lettre
      z
      
      ********
      
      
       donnez une lettre
      z
      
      ********
      
      
       donnez une lettre
      z
      
      ********
      
      
       donnez une lettre
      z
      
      ********
      
      
       donnez une lettre
      z
      
      ********
      
      
       donnez une lettre
      C
      
      C*******
      
      
       donnez une lettre
      h
      
      Ch******
      
      
       donnez une lettre
      o
      
      Cho*o***
      
      
       donnez une lettre
      c
      
      Choco***
      
      
      
      desole tu as perdu

      Mais j'étais en train de deviner le mot ! Il y a un bug quelque part, ça n'aurait pas du me prendre ça pour un "coup" si j'ai rentré une bonne lettre.

      Aussi, tu pourrais stocker une liste de lettres : si je rentre une lettre qui est déjà dans la liste, tu me dis "lettre déjà rentrée" mais tu ne me comptes pas un coup.

      Aussi, ça me sélectionne toujours "Chocolat" : je pense qu'il doit y avoir un bug dans ton aléatoire pour choisir un mot.

      En résumé, en bugs :

      - Tu décomptes un coup même si la lettre rentrée est correcte
      - Tu sélectionnes toujours le même mot, problème dans l'aléatoire
      - Si test.txt n'existe pas, le programme plante 

      En améliorations possibles :

      - Afficher le nombre de coups restants
      - Ignorer la casse des lettres
      - Stocker une liste des lettres déjà rentrées, et ne pas compter le coup si on indique une lettre "déjà dite" 

      ça c'est pour la fonctionnalité du code. Maintenant pour la forme, en vrai c'est pas trop mal - tu as découpé en plusieurs fonctions ce qui est super, par contre fait vraiment attention à l'indentation, c'est important. Sur Code::Blocks il me semble que tu as un truc quelque part dans les menus qui te permet de réindenter comme il faut.

      D'ailleurs ta variable i de generemot n'est utilisée nulle part. C'est peut-être pour ça que ça tire toujours le même mot ?




      • Partager sur Facebook
      • Partager sur Twitter
        9 mai 2019 à 17:59:50

        bonjour 

        merci de ta patience et pour ton analyse

        je bosse sur visual studio code et non sur codeblocks,j'ai commencé les cours sur une chaine youtube,je viens ici pour approndir un peu plus.

        je compile via la console avec gcc et je ne sais pas encore utilisé gdb(un cours ici?)

        cependant la variable i que tu m'evoques me genere un nombre aleatoire:

         int i=(rand()%(MAX-MIN+1)-MIN);

        tant que le compteur est <=  i ,je lis ligne par ligne.

        enfin chacun de mes mots est different chez moi....

        cependant tes remarques sont justes et je vois que je dois bien ameliorer le truc.....

        je vais modifier plusieurs choses,encore merci de tes suggestions !!!!!

        • Partager sur Facebook
        • Partager sur Twitter
          10 mai 2019 à 0:59:01

          guth62 a écrit:

          bonjour 

          merci de ta patience et pour ton analyse

          je bosse sur visual studio code et non sur codeblocks,j'ai commencé les cours sur une chaine youtube,je viens ici pour approndir un peu plus.

          je compile via la console avec gcc et je ne sais pas encore utilisé gdb(un cours ici?)

          cependant la variable i que tu m'evoques me genere un nombre aleatoire:

           int i=(rand()%(MAX-MIN+1)-MIN);

          tant que le compteur est <=  i ,je lis ligne par ligne.

          enfin chacun de mes mots est different chez moi....

          cependant tes remarques sont justes et je vois que je dois bien ameliorer le truc.....

          je vais modifier plusieurs choses,encore merci de tes suggestions !!!!!


          Ah yes exact j'avais mal lu ton for. Vu que tu n'avais pas mis d'espace entre la comparaison et i mon cerveau ne l'avait pas vu

          En fait ce qu'il se passe c'est que si tu ne mets que 4 mots dans ton test.txt, i va être généré entre 1 et 30 - donc dans 26 cas sur 30 je vais tomber sur le dernier mot, c'est à dire Chocolat dans mon cas. Il faudrait plutôt prendre le nombre de lignes du fichier par exemple. Mais bon, c'est encore une autre amélioration ;)

          C'est déjà cool si tu sais compiler avec gcc ! Pour utiliser gdb tu dois d'abord compiler avec l'option -g, puis tu fais "gdb ton_binaire".

          Avec gdb tu peux : exécuter instruction par instruction.. exécuter jusqu'à un certain point.. printer n'importe quelle variable qui te vient à l'esprit.. afficher la pile d'appel des fonctions.. Pour déboguer le Segmentation Fault, j'ai fait ces deux commandes GDB : d'abord run, pour exécuter jusqu'au bout - puis backtrace : j'ai alors vu que le seg fault est arrivé à telle ligne.

          Y a un cours sur GDB ici : https://openclassrooms.com/fr/courses/1140636-deboguer-son-programme-avec-gdb

          Sinon, je trouve que les concepts sont pas difficiles à appréhender (à part peut être "watchpoint" : ça sert à arrêter l'exécution dès qu'une variable ou emplacement mémoire est modifié), en fait en utilisant une cheatsheet et en essayant les commandes par toi même c'est assez facile à prendre en main

          https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf

          A noter que la plupart des IDE comme Visual Studio ont déjà un débogueur intégré graphique - c'est à dire que tu peux mettre des breakpoint (point d'arrêt) en cliquant sur tes lignes etc.. En interne les IDEs font appel à GDB bien sûr, mais en visuel c'est peut être plus sympa qu'en ligne de commande. Tout dépend des gouts

          • Partager sur Facebook
          • Partager sur Twitter

          tuto le pendu

          × 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