Partage
  • Partager sur Facebook
  • Partager sur Twitter

malloc() ne renvoie pas la valeur attendue

Contexte: TD n°2/Jeu du Pendu

Sujet résolu
Anonyme
    16 janvier 2021 à 22:02:06

    Bonsoir à la brave plèbe.

    Voyez-vous, je butte actuellement sur le deuxième TD du cours en C, celui avec le jeu du pendu, comme ceux qui ont lu le sous-titre du sujet savent déjà. Or voyez-vous, dans la première phase de mon programme où les variables s'initialisent et où les volumes des tableaux s'ajustent à la longueur du mot à trouver, la fonction malloc, présentée dans le chapitre sur l'allocation dynamique, ne restitue pas la valeur que j'attendais d'elle, à savoir 4, qui est censée être le volume du tableau qui va devoir remplir la chaîne de caractères qui va s'afficher à l'écran et se révéler peu à peu au joueur, et qui doit être égale en longueur à la chaîne de caractères contenant le mot à trouver, lui-même. Voici la section du code en question:

    int main()
    {
    
        int i, test_positif, indice_valide, quant_lettres = 0;
        char lettreIndice;
        char motsecret[32] = "TEST";
    
        for (i = 0; motsecret[i] != '\0'; ++i){
            quant_lettres++;
        }
        printf("La taille du mot est de %d caracteres.\n\n", quant_lettres);
    
        char *motsecret_cache = NULL;
        motsecret_cache = malloc(quant_lettres * sizeof(char));
    
        printf("%s", motsecret_cache);
        quant_lettres = 0;
        printf("Test: nombre de cases dans motsecret_cache:\n");
        for (i = 0; motsecret_cache[i] != '\0'; ++i){
            quant_lettres++;
        }
        printf("%d", quant_lettres);
        printf("%s", motsecret);
    
    
        for (i = 0; motsecret_cache[i] != '\0'; ++i){
            motsecret_cache[i] = '*';
        }
        printf("%s", motsecret_cache);
    [...]

    Comme vous pouvez le voir, j'ai ajouté quantité de printf afin de suivre l'action du code pendant les tests et constater clairement où se trouvent les problèmes quand ils surviennent. Quand j'exécute le programme, celui-ci renvoit les lignes suivantes sur le tableau de commandes:

    La taille du mot est de 4 caracteres.

    0q▬Test: nombre de cases dans motsecret_cache:

    3TEST***Veuillez indiquer une lettre de votre choix:

    La deuxième et la troisième ligne montrent bien que le programme ne renvoit pas la valeur de la longueur de la chaîne de caractères qui doit servir de modèle au test. Quelle peut bien en être la raison? Passez une bonne soirée, d'ici-là.

    • Partager sur Facebook
    • Partager sur Twitter
      16 janvier 2021 à 22:14:20

      Salut,

      malloc ne renvoie pas une taille, ça te renvoie une adresse. Et donc ça peut varier d'un lancement à l'autre.

      malloc, ça veut dire "trouve moi 4 octets". S'il te renvoie NULL c'est que ça a foiré, sinon il te renvoie l'endroit ou il a trouvé ces octets, et pas de taille. A toi ensuite de mettre ce que tu veux dedans.

      • Partager sur Facebook
      • Partager sur Twitter

      Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

      Anonyme
        16 janvier 2021 à 22:15:20

        Quand je dis "renvoyer une taille", je veux dire "une adresse de tableau dont le volume sera équivalent à celui de la chaîne correspondant au mot à trouver". Et je constate qu'il renvoit un tableau dont la longueur ne correspond pas à la taille que je souhaite, quand bien même j'ai veillé à indiquer la variable qui sert strictement à indiquer la longueur de la chaîne de caractère, à la fonction.

        -
        Edité par Anonyme 16 janvier 2021 à 22:16:36

        • Partager sur Facebook
        • Partager sur Twitter
          16 janvier 2021 à 22:44:15

          malloc te renvois bien l'adresse de ton bloc mémoire alloué et il fait bien 4 octets dans ton code ! Ce sont tes tests qui sont foireux !

          Quand malloc a alloué la mémoire, il ne l'initialise pas, alors il y a n'importe quoi dedans, et toi tu essais de l'afficher comme si cela était une chaîne de caractère, forcement ça affiche n'importe quoi et tu calcules la longueur comme si cela était une chaîne de caractère, donc ça affiche n'importe quoi !

          -
          Edité par rouloude 16 janvier 2021 à 22:44:26

          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            16 janvier 2021 à 23:03:02

            J'ai surtout essayé de transmettre la valeur de la première chaine de caractère comme indicateur pour créer un tableau de longueur correspondante. Mais je n'arrive pas à me servir de cette fonction malloc()!

            -
            Edité par Anonyme 16 janvier 2021 à 23:04:45

            • Partager sur Facebook
            • Partager sur Twitter
              16 janvier 2021 à 23:33:43

              Hello,

              char str[]="Je teste malloc()";
              int len=strlen(str);
              char *new_str=malloc(len+1);
              strcpy(new_str,str);
              new_str[0]='I';
              new_str[1]='l';
              printf("%s\n%s\n",str,new_str);
              


              Edit: merci @PierrotLeFou

              -
              Edité par edgarjacobs 17 janvier 2021 à 14:40:26

              • Partager sur Facebook
              • Partager sur Twitter
                17 janvier 2021 à 1:48:13

                @edgarjacobs: je lis "stcpy" au lieu de "strcpy"
                @saphintosh:
                edgarjacobs a voulu te montrer quelques petites choses:
                + il faut réserver un espace de plus pour la fin de la chaîne (ou tableau de char).
                (la fin de chaîne c'est le caractère '\0')
                + il faut recopier quelque chose dans le tableau réservé par malloc(), Ça ne s'initialise pas tout seul.
                (ici, c'est strcpy() qui fait la copie de l'ancienne chaîne dans la nouvelle)
                + on peut modifier le contenu de cette chaîne.
                (ici, "Je" est remplacé par "Il")
                • Partager sur Facebook
                • Partager sur Twitter

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

                Anonyme
                  5 février 2021 à 10:17:41

                  Bonjour, désolé d'avoir mis tant de temps à répondre, je perds facilement ma motivation quand j'arrive pas à faire ce que je m'étais imposé. Donc, j'ai repris le code proposé par EdgarJacobs, avec les espaces en plus et en remplaçant les noms des variables par des termes plus pertinents dans le cadre du TP. Voici ce que ça donne, dans la séquence en question: 

                  int i, quant_lettres = 0;
                      char lettreIndice;
                      char motsecret[sizeof(int)] = "TEST";
                  
                      quant_lettres = strlen(motsecret); //Je reprends le code de Edgar
                      printf("La taille du mot est de %d caracteres.\n\n", quant_lettres); //Je teste. La console renvoit bien la quantité de caractères dans le mot "Test"
                  
                      char *motsecret_cache = malloc(quant_lettres); //J'attribue au cache qui servira à afficher les lettres déjà découvertes une adresse ainsi que la longueur du tableau qu'il aura à stocker
                  
                      for (i = 0; motsecret_cache[i] != '\0'; i++){
                          motsecret_cache[i] = '*';
                      }//Je remplace les caractères du cache par un joker provisoirement jusqu'à ce que le caractère entré corresponde avec le mot secret en mémoire.
                      printf("%s", motsecret_cache);//Je teste

                  Or, en lançant le programme, j'obtiens en console la chose suivante: 
                  "La taille du mot est de 4 caractères (bon jusque-là ça se tient, puis:)

                  ******"

                  6 jokers. Pourtant, je n'aurais dû avoir qu'autant de jokers qu'il n'y avait de caractères dans le mot "TEST", à savoir 4, d'autant que j'ai utilisé la fonction strlen(motsecret) pour attribuer à motsecret_cache. J'avais même essayé à la base avec un "+1" comme recommandé dans la réponse d'Edgar, mais à quoi bon ajouter un espace quand il y a déjà trop de caractères par rapport à ce que le tableau était censé stocker? Ou ai-je merdé? Merci d'avance.

                  Edit:

                  J'ai tenté de tester la longueur de la chaîne motsecret_cache avec un printf("%s", strlen(motsecret_cache)) et j'obtiens un 3. Je fais un +1 correspondant au caractère '\0' dans la chaine originale à la fonction char *motsecret_cache = malloc(quant_lettres), et voilà que j'obtiens un 2. Voilà qui n'arrange pas les choses.

                  Edit:

                  Bon oubliez ça. En fait, la solution était toute bête. Le code que j'ai envoyé n'était qu'une fraction de mon main.c. En fait, le print("%s", motsecret_cache) se répétait dans les lignes suivantes sans que je l'eus remarqué. Je vous ai dérangé pour rien, je veillerais que ce soit pour quelque chose d'utile la fois suivante.

                  Réponse à Magma:

                  Serais-ce au sujet de la confusion que j'ai eu par rapport au %d que j'ai mis à la place du %s, que je viens de corriger? Il ne s'agit pas d'une erreur d'assimilation du concept de chaîne de caractères, mais d'un oubli, dans la frustration d'avoir à retranscrire précisément ce que j'ai fais dans mon programme.

                  -
                  Edité par Anonyme 5 février 2021 à 10:52:58

                  • Partager sur Facebook
                  • Partager sur Twitter
                    5 février 2021 à 10:46:50

                    Tu mets la charrue avant les bœufs !

                    Tu tentes de faire le "Jeu du pendu" avant d'avoir assimilé ce qu'est une chaine de caractères en C ...

                    • Partager sur Facebook
                    • Partager sur Twitter
                      5 février 2021 à 11:05:09

                      Tu n'as pas le résultat attendu car tu ne tiens pas compte de ce que l'on te dit

                      #include <stdio.h>
                      #include <stdlib.h>
                      #include <string.h>
                      
                      int main(void) {
                          char motsecret[] = "TEST";  /* on peut aussi faire char motsecret[5]
                                                       * là, on laisse le compilateur déterminer
                                                       * la bonne taille nécessaire 
                                                       * ton char motsecret[sizeof(int)] n'a 
                                                       * aucun sens */
                      
                          int quant_lettres = strlen(motsecret);
                          printf("La taille du mot est de %d caracteres.\n\n", quant_lettres);
                      
                          /* il faut allouer un char de plus que le nombre de lettres
                           * car il faut un espace additionnel pour le caractère
                           * terminateur '\0' */
                          char *motsecret_cache = malloc(quant_lettres + 1);
                      
                          /* puisqu'on dispose du nombre de lettres, on s'en sert pour
                           * borner la boucle */
                          for (int i = 0; i < quant_lettres; i++) {
                              motsecret_cache[i] = '*';
                          }
                          printf("Mot secret : %s\n", motsecret_cache);
                      
                          return 0;
                      }
                      


                      -
                      Edité par Dlks 5 février 2021 à 11:11:06

                      • Partager sur Facebook
                      • Partager sur Twitter
                        5 février 2021 à 11:11:01

                        Attention le code de Dlks ne finit pas la chaine motsecret_cache par 0, le plus simple est d'utiliser calloc pour pas s'emmerder.
                        • Partager sur Facebook
                        • Partager sur Twitter
                        l'azerty est aux dispositions ce que subversion est aux SCM
                          5 février 2021 à 11:18:20

                          Merci markand, le code serait :

                          #include <stdio.h>
                          #include <stdlib.h>
                          #include <string.h>
                          
                          int main(void) {
                              char motsecret[] = "TEST";  /* on peut aussi faire char motsecret[5]
                                                           * là, on laisse le compilateur déterminer
                                                           * la bonne taille nécessaire 
                                                           * ton char motsecret[sizeof(int)] n'a 
                                                           * aucun sens */
                          
                              int quant_lettres = strlen(motsecret);
                              printf("La taille du mot est de %d caracteres.\n\n", quant_lettres);
                          
                              /* il faut allouer un char de plus que le nombre de lettres
                               * car il faut un espace additionnel pour le caractère
                               * terminateur '\0' */
                              char *motsecret_cache = malloc(quant_lettres + 1);
                          
                              /* puisqu'on dispose du nombre de lettres, on s'en sert pour
                               * borner la boucle */
                              for (int i = 0; i < quant_lettres; i++) {
                                  motsecret_cache[i] = '*';
                              }
                              /* comme le rappelle markand il faut veiller à terminer 
                               * cette chaîne également ou alternativement utiliser calloc
                               * au lieu de malloc, qui met à zéro l'espace mémoire alloué */
                              motsecret_cache[quant_lettres] = '\0';
                              printf("Mot secret : %s\n", motsecret_cache);
                          
                              return 0;
                          }
                          



                          -
                          Edité par Dlks 5 février 2021 à 11:21:35

                          • Partager sur Facebook
                          • Partager sur Twitter
                            5 février 2021 à 11:34:00

                            saphintosh a écrit:

                            Edit :

                            Bon oubliez ça. En fait, la solution était toute bête. 

                            Non, c'est bourré d'erreur ! Il faut que tu revois ça avant d'allé plus loin dans ton cours. Il faut même revenir en arrière !

                            Parce que ça commence très mal :

                            -

                            char motsecret[sizeof(int)] = "TEST";

                            Sais-tu ce que signifie l'opérateur sizeof ?

                            -

                            for (i = 0; motsecret_cache[i] != '\0'; i++){
                                    motsecret_cache[i] = '*';
                                }

                            Et ici tu test le caractère de fin de chaîne pour mettre fin à la boucle, mais tu l'as mis quand dans le tableau motsecret_cache et avais-tu la place de le mettre ?



                            • Partager sur Facebook
                            • Partager sur Twitter
                              5 février 2021 à 13:54:03

                              Je pense que l'OP pose des questions sur un forum mais sans jamais lire les réponses.
                              • Partager sur Facebook
                              • Partager sur Twitter
                              l'azerty est aux dispositions ce que subversion est aux SCM
                                5 février 2021 à 15:26:25

                                saphintosh a écrit:

                                ....j'ai repris le code proposé par EdgarJacobs....

                                Absolument pas.

                                saphintosh a écrit:

                                    char *motsecret_cache = malloc(quant_lettres);
                                


                                Où as-tu vu ça dans mon code ? Dans mon code, cette ligne est écrite

                                char *new_str=malloc(len+1);
                                


                                -
                                Edité par edgarjacobs 5 février 2021 à 15:29:56

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Anonyme
                                  5 février 2021 à 15:30:44

                                  Là:

                                  char*new_str=malloc(len+1);

                                  En adaptant le nom des variables à leur utilisation dans le programme. Quand au "t'as pas mis le +1", non seulement la valeur de la variable ne correspondait pas à celle qu'elle devait donner, mais je suis tombé à une valeur de 2 caractères signalés par mon code, ce qui est quand même fort. Le "+" s'est comporté comme un "-".

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  malloc() ne renvoie pas la valeur attendue

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