Partage
  • Partager sur Facebook
  • Partager sur Twitter

Allocation dynamique d'un tableau à deux dimensios

Sujet résolu
    6 août 2019 à 16:52:43

    Bonjour,

    Je suis débutant en programmation c et je suis les cours de Jason Champagne sur utube: .https://www.youtube.com/watch?v=71QV6fFl_bk&list=PLrSOXFDHBtfEh6PCE39HERGgbbaIHhy4j&index=15

    J'en suis à l'allocation dynamique je connais maintenant les fonctions malloc realloc calloc et sizeof.

    Ce que je voudrai faire c'est alloué dynamiquement un tableau à deux dimensions.

    J'ai faits le code suivant :

    23         // Allocation dynamique à deux dimensions
     24         int nombre_ligne = 3;
     25         int nombre_colonne = 2;
     26         int** tableau = NULL;
     27         for (int i = 0; i < nombre_ligne ; i++)
     28         {
     29                 tableau = malloc(sizeof(int*) * nombre_ligne);
     30 
     31                 for (int j = 0; j < nombre_colonne; j++)
     32                 {
     33                         tableau[i] = malloc(sizeof(int) * nombre_colonne);
     34                         tableau[i][j] = 1;
     35                         printf("%d", tableau[i][j]);
     36 
     37                 }
     38         }
     39 
     40         free(tableau);
    

    Mais j'ai une erreur de segmentation et le compilateur ne me donne aucun indice je compile parfaitement donc je ne sais pas quoi faire pour résoudre le problème.

    Pouvez vous m'aidez s'il vous plait.

    • Partager sur Facebook
    • Partager sur Twitter
      6 août 2019 à 18:02:52

      Salut,

      Il faut affecter une "colonne" à chaque "ligne". De plus, tu as imbriqué les boucles et ton premier malloc est dans la boucle.

      -
      Edité par drx 6 août 2019 à 18:07:46

      • Partager sur Facebook
      • Partager sur Twitter

      Bonhomme !! | Jeu de plateforme : Prototype.

        6 août 2019 à 18:25:00

        merci drx j'ai corrigé et maintenant ca fonctionne très bien le code ci dessous :

        1 #include <stdio.h>
          2 #include <stdlib.h>
          3 
          4 int main(void)
          5 {
          6         int nombre_ligne = 3;
          7         int nombre_colonne = 2;
          8         int **tableau = NULL;
          9         tableau = malloc(sizeof(*tableau) * nombre_ligne);
         10         for (int i = 0; i < nombre_ligne; i++)
         11         {
         12                 for (int k = 0; k < nombre_colonne; k++)
         13                 {
         14                         tableau[i] = malloc(sizeof(**tableau) * nombre_colonne);
         15                         tableau[i][k] = 1;
         16                         printf("%d", tableau[i][k]);
         17                 }
         18         }
         19         free(tableau);
         20         return 0;
         21 }
        

        et si je veux faire maintenant une allocation dynamique à trois dimensions je faits comment ?



        • Partager sur Facebook
        • Partager sur Twitter
          6 août 2019 à 18:35:46

          Avec une troisieme boucle. Une boucle par dimension.
          • Partager sur Facebook
          • Partager sur Twitter
            6 août 2019 à 18:49:10

            Mais dans l'esprit je ne comprends pas c'est à dire que pour un tableau à deux dimensions on associe à chaque ligne une colonne ok ça j'ai compris.

            Mais pour un tableau à trois dimensions j'ai du mal à visualiser dans ma tête.

            Je vais essayer de coder quelque chose en attendant.

            J'ai du mal à le voir en mémoire.

            -
            Edité par PierreBoutier1 6 août 2019 à 19:14:12

            • Partager sur Facebook
            • Partager sur Twitter
              6 août 2019 à 18:55:44

              Salut,

              Sauf que ce n'est toujours pas bon.

              Il te faut un papier et un crayon.

              1 -> tu alloues 3 lignes et tu obtiens une table[3]. Tu dois donc attribuer une colonne à chaque ligne. Ton second malloc est donc mal placé.

              2 -> fuite mémoire sur ton malloc en boucle.

              - allouer ligne.

              - pour (1) chaque ligne allouer une colonne.

              - pour (2) chaque colonne attribuer une valeur.

              - fin (2)

              - fin(1)

              • Partager sur Facebook
              • Partager sur Twitter

              Bonhomme !! | Jeu de plateforme : Prototype.

                6 août 2019 à 19:27:11

                drx je ne te comprends pas c'est exactement ce que je faits.

                J'ai mis des commentaires pour qu'on soit bien claire.

                1 #include <stdio.h>
                  2 #include <stdlib.h>
                  3 
                  4 int main(void)
                  5 {
                  6         int nombre_ligne = 3;
                  7         int nombre_colonne = 2;
                  8         int **tableau = NULL;
                  9         tableau = malloc(sizeof(*tableau) * nombre_ligne); // Allocation du nombre de ligne 
                 10         for (int i = 0; i < nombre_ligne; i++)
                 11         {
                 12                 for (int k = 0; k < nombre_colonne; k++)
                 13                 {
                 14                         tableau[i] = malloc(sizeof(**tableau) * nombre_colonne); // Pour une ligne j'associe une colonne 
                 15                         tableau[i][k] = 1; // Je donne une valeur ligne colonne à mon tableau 
                 16                         printf("%d", tableau[i][k]);
                 17                 }
                 18         }
                 19         free(tableau); // je libere mon pointeur pour éviter les fuites mémoires 
                 20 
                 21         return 0;
                 22 }
                



                • Partager sur Facebook
                • Partager sur Twitter
                  6 août 2019 à 20:14:17

                  Non ! l'allocation des colonnes doit être dans la boucle for i , pas dans la boucle for k !

                  Comme tu fais, tu fait l'allocation de la case tableau[i] nombre_colonne fois. alors que l'allocation tu dois la faire une seule fois.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 août 2019 à 20:34:16

                    ha d'accord merci rouloude c'est plus clair comme ça

                    Je vais essayer d'allouer de la mémoire dynamiquement à un tableau à trois dimension

                    Je ne clos pas encore le sujet je vais vous montrer un bout de code sur un tableau à trois dimension.

                    Pour alloué dynamiquement un tableau à trois dimension j'ai fait ça je ne suis pas du tout sur de moi mais ça compile et j'ai un affichage qui semble correct.

                    Es ce que cela vous semble juste.

                    Merci encore pour votre aide.

                    1 #include <stdio.h>
                      2 #include <stdlib.h>
                      3 
                      4 int main(void)
                      5 {
                      6 //      int nombre_ligne = 3;
                      7 //      int nombre_colonne = 2;
                      8 //      int **tableau = NULL;
                      9 //      tableau = malloc(sizeof(*tableau) * nombre_ligne); // Allocation du nombre de ligne
                     10 //      for (int i = 0; i < nombre_ligne; i++)
                     11 //      {
                     12 //              tableau[i] = malloc(sizeof(**tableau) * nombre_colonne); // Pour une ligne j'associe une colonne
                     13 //              for (int k = 0; k < nombre_colonne; k++)
                     14 //              {
                     15 //                      tableau[i][k] = 1; // Je donne une valeur ligne colonne à mon tableau
                     16 //                      printf("%d", tableau[i][k]); 
                     17 //              } 
                     18 //      }
                     19 //      free(tableau); // je libere mon pointeur pour éviter les fuites mémoires
                     20 
                     21         int premiere_dimension = 3;
                     22         int deuxieme_dimension = 2;
                     23         int troisieme_dimension = 1;
                     24 
                     25         int*** tableau = NULL;
                     26         tableau = malloc(sizeof(*tableau) * premiere_dimension); // allocation mémoire de la premiere dimension
                     27         for (int i = 0; i < premiere_dimension; i++)
                     28         {
                     29                 tableau[i] = malloc(sizeof(**tableau) * deuxieme_dimension); // allocation mémoire de la deuxieme dimension
                     30                 for (int j = 0; j < deuxieme_dimension; j++)
                     31                 {
                     32                         tableau[i][j] = malloc(sizeof(***tableau) * troisieme_dimension);
                     33 
                     34                         for (int k=0; k < troisieme_dimension; k++)
                     35                         {
                     36                                 tableau[i][j][k] = 1;
                     37                                 printf("%d", tableau[i][j][k]);
                     38                         }
                     39 
                     40                 }
                     41         }
                     42         free(tableau); 
                     43 
                     44         return 0;
                     45 }
                    

                    -
                    Edité par PierreBoutier1 6 août 2019 à 22:14:33

                    • Partager sur Facebook
                    • Partager sur Twitter
                      7 août 2019 à 8:48:21

                      Salut,

                      ça y ressemble. Sauf que tu ne vérifies pas ton allocation. Il faut donc l'ajouter. à titre d'exercice, je te propose de la mettre en place et de coder la libération mémoire en cas d'erreur.

                      -
                      Edité par drx 7 août 2019 à 8:49:39

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Bonhomme !! | Jeu de plateforme : Prototype.

                        7 août 2019 à 11:47:01

                        Bonjour,

                        Il y a une méthode beaucoup plus simple pour un tableau à 2 dimensions:

                        Soit ARRAY_WIDTH et ARRAY_HEIGHT deux constantes (ou bien utiliser des variables à la place si on ne connaît pas la taille du tableau à l'avance).

                        Il suffit d'allouer ARRAY_WIDTH * ARRAY_HEIGHT en un seul coup , ce qui fait que l'on a à vérifier une seule allocation et on accède aux case du tableau avec la code suivant: array_ptr[x * ARRAY_HEIGHT + x] et en plus c'est cache friendly donc c'est optimisé. Exemple:

                        void allocate(FILE *errorLog , Type **array_ptr, unsigned width, unsigned height )
                        {
                             *array_ptr = malloc( width * height * size_of(Type) );       
                        
                             if( !array_ptr )
                             {
                                  fprintf(errorLog, "Error: couldn't allocate space for array\n"
                             }
                        }

                        Bien sur la fonction ci-dessus peut -être codée différemment, par exemple elle peut renvoyer un malloc (via return) et on traite l'erreur à l'extérieur, le C étant multi paradigme. :)

                        P.S. : hônnetement vérifier les sous allocations une à une et élaborer des mécanismes pour sortir de toutes ces allocations tiens plus de la prise de tête que d'une solution simple.

                        Re P.S: avec une structure on peut enregistrer les infos de la matrice pour les transporter dans les différentes fonctions assez simplement, par exemple:

                        struct Matrix
                        {
                            size_t width;
                            size_t height;
                            Type* array_ptr;
                        };

                        Tout simplement

                        -
                        Edité par Warren79 7 août 2019 à 11:51:43

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Mon site web de jeux SDL2 entre autres : https://www.ant01.fr

                          7 août 2019 à 13:06:47

                          Bonjour,

                          Je dirais qu'il existe au moins trois formes possibles. Je prend l'exemple de 3 dimensions :
                          - le tableau de tableaux de tableaux : Type*** tableau1 qui va demander de nombreuses allocations.
                          - le tableau linéarisé : Type* tableau2 qui ne demande qu'une seule allocation. Si les dimensions sont des constantes il a un équivalent Type tableau3[NB_COL*NB_LIG*NB_PROF].
                          - le tableau à 3 dimensions : Type* tableau4[NB_LIG][NB_COL] qui lui aussi ne demande qu'une allocation mais exige que les 2 premières dimensions soient des constantes compilation. Si les 3 sont constantes, son équivalent est Type tableau5[NB_COL][NB_LIG][NB_PROF].

                          tableau1, tableau4 et tableau5 s'utilisent de la même manière : tableau[k][j][i].
                          tableau2 et tableau3 nécessitent une formule pour accéder aux éléments : tableau[k*nb_col*nb_lig + j*nb_col + i].

                          • Partager sur Facebook
                          • Partager sur Twitter

                          En recherche d'emploi.

                            7 août 2019 à 16:18:08

                            J'ai rajouté  les mesure de controle de l'allocation dynamique de mémoire dans mon code ci dessous es ce que c'est bon maintenant drx ?

                            Le code ci dessous merci encore pour votre aide.

                            21         int premiere_dimension = 3;
                             22         int deuxieme_dimension = 2;
                             23         int troisieme_dimension = 1;
                             24 
                             25         int*** tableau = NULL;
                             26         tableau = malloc(sizeof(*tableau) * premiere_dimension); // allocation mémoire de la premiere dimension
                             27         if(tableau == NULL)
                             28                 exit(1);
                             29         for (int i = 0; i < premiere_dimension; i++)
                             30         {
                             31                 tableau[i] = malloc(sizeof(**tableau) * deuxieme_dimension); // allocation mémoire de la deuxieme dimension
                             32                 if (tableau[i] == NULL)
                             33                                 exit(1);
                             34                 for (int j = 0; j < deuxieme_dimension; j++)
                             35                 {
                             36                         tableau[i][j] = malloc(sizeof(***tableau) * troisieme_dimension); 
                             37                         if (tableau[i][j] == NULL) 
                             38                                 exit(1);
                             39                         for (int k=0; k < troisieme_dimension; k++)
                             40                         {
                             41                                 tableau[i][j][k] = 1;
                             42                                 printf("%d", tableau[i][j][k]);
                             43                         }
                             44 
                             45                 }
                             46         }
                             47         free(tableau);
                            



                            -
                            Edité par PierreBoutier1 7 août 2019 à 16:18:43

                            • Partager sur Facebook
                            • Partager sur Twitter
                              7 août 2019 à 17:20:49

                              Bonjour,

                              @PierreBoutier1 : dans ton code ci-dessus tu ne fais qu'un seul free() (tout à la fin) alors que tu as plusieurs malloc() . Il faut faire autant de free qu'il y a de malloc() . ;)

                              Ce n'est pas parce que les OS modernes font automatiquement le ménage à la fin de ton programme qu'il faut coder comme des cochons.:p (dit sur le ton de la plaisanterie, hein ).

                              • Partager sur Facebook
                              • Partager sur Twitter

                              Mon site web de jeux SDL2 entre autres : https://www.ant01.fr

                                7 août 2019 à 17:35:04

                                Hello,

                                Il y a 3 malloc() dans ton code, dont 2 dans des boucles. Mais je ne vois qu'un seul free(). Le grand principe: à chaque malloc() son free() !

                                Wooups: grillé

                                -
                                Edité par edgarjacobs 7 août 2019 à 17:35:45

                                • Partager sur Facebook
                                • Partager sur Twitter

                                On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                                  7 août 2019 à 22:56:54

                                  ok à chaque malloc un free c'est noté pour codé proprement.

                                  Je viens de le corriger. Mon code ci dessous.

                                  Es ce que c'est la bonne cette fois :).

                                  6         tableau = malloc(sizeof(*tableau) * premiere_dimension); // allocation mémoire de la premiere dimension
                                   27         free(tableau);
                                   28         if(tableau == NULL)
                                   29                 exit(1);
                                   30         for (int i = 0; i < premiere_dimension; i++)
                                   31         {
                                   32                 tableau[i] = malloc(sizeof(**tableau) * deuxieme_dimension); // allocation mémoire de la deuxieme dimension
                                   33                 if (tableau[i] == NULL)
                                   34                                 exit(1);
                                   35                 free(tableau[i]);
                                   36                 for (int j = 0; j < deuxieme_dimension; j++)
                                   37                 {               
                                   38                         tableau[i][j] = malloc(sizeof(***tableau) * troisieme_dimension); 
                                   39                         if (tableau[i][j] == NULL) 
                                   40                                 exit(1); 
                                   41                         free(tableau[i][j]); 
                                   42                         for (int k=0; k < troisieme_dimension; k++) 
                                   43                         {       
                                   44                                 tableau[i][j][k] = 1; 
                                   45                                 printf("%d", tableau[i][j][k]); 
                                   46                         } 
                                   47                                 
                                   48                 }               
                                   49         }               
                                  


                                  -
                                  Edité par PierreBoutier1 7 août 2019 à 22:58:15

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    7 août 2019 à 23:24:10

                                    Les free, il faut les faire quand tu n'as plus besoin de ton tableau !
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      8 août 2019 à 0:34:03

                                      Comment ça je ne comprends pas je pensais que free libérai la mémoire une fois que le programme est terminé.

                                      Ha oui effectivement je n'avais pas testé mais j'ai une erreur de segmentation lorsque je place mes free à cette endroit.

                                      Bon cette fois j'ai libéré mon tableau une fois que j'ai inscrit les valeurs dedans.

                                      J'ai vérifier ça compile et j'ai un affichage correct.

                                      Le code ci dessous encore une fois merci pour votre aide.

                                      25         int*** tableau = NULL;
                                       26         tableau = malloc(sizeof(*tableau) * premiere_dimension); // allocation mémoire de la premiere dimension
                                       27         if(tableau == NULL)
                                       28                 exit(1);
                                       29         for (int i = 0; i < premiere_dimension; i++)
                                       30         {
                                       31                 tableau[i] = malloc(sizeof(**tableau) * deuxieme_dimension); // allocation mémoire de la deuxieme dimension
                                       32                 if (tableau[i] == NULL)
                                       33                                 exit(1);
                                       34                 for (int j = 0; j < deuxieme_dimension; j++)
                                       35                 {
                                       36                         tableau[i][j] = malloc(sizeof(***tableau) * troisieme_dimension);
                                       37                         if (tableau[i][j] == NULL)
                                       38                                 exit(1);
                                       39                         for (int k=0; k < troisieme_dimension; k++)
                                       40                         {
                                       41                                 tableau[i][j][k] = 1;
                                       42                                 printf("%d", tableau[i][j][k]);
                                       43                         }
                                       44 
                                       45                 }
                                       46         }
                                       47 
                                       48         for (int i = 0; i < premiere_dimension; i++)
                                       49                 free(tableau[i]);
                                       50 
                                       51         for (int i = 0; i < premiere_dimension; i++)
                                       52                 for (int j = 0; j < deuxieme_dimension; j++)
                                       53                         free(tableau[i][j]);
                                       54         free(tableau);
                                      



                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        8 août 2019 à 1:13:32

                                        Attention à l'ordre des free, quand tu fais free(tableau[i][j]) tu utilises tableau[i] que tu as déjà libéré auparavant.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          8 août 2019 à 15:08:55

                                          ok j'ai rectifié es ce que maintenant mon code est propre ?

                                          1         int premiere_dimension = 3;
                                           22         int deuxieme_dimension = 2;
                                           23         int troisieme_dimension = 1;
                                           24 
                                           25         int*** tableau = NULL;
                                           26         tableau = malloc(sizeof(*tableau) * premiere_dimension); // allocation mémoire de la premiere dimension
                                           27         if(tableau == NULL)
                                           28                 exit(1);
                                           29         for (int i = 0; i < premiere_dimension; i++)
                                           30         {
                                           31                 tableau[i] = malloc(sizeof(**tableau) * deuxieme_dimension); // allocation mémoire de la deuxieme dimension
                                           32                 if (tableau[i] == NULL)
                                           33                                 exit(1);
                                           34                 for (int j = 0; j < deuxieme_dimension; j++)
                                           35                 {
                                           36                         tableau[i][j] = malloc(sizeof(***tableau) * troisieme_dimension);
                                           37                         if (tableau[i][j] == NULL)
                                           38                                 exit(1);
                                           39                         for (int k=0; k < troisieme_dimension; k++)
                                           40                         {
                                           41                                 tableau[i][j][k] = 1;
                                           42                                 printf("%d", tableau[i][j][k]);
                                           43                         }
                                           44 
                                           45                 }
                                           46         }
                                           47 
                                           48 
                                           49         for (int i = 0; i < premiere_dimension; i++)
                                           50                 for (int j = 0; j < deuxieme_dimension; j++)
                                           51                         free(tableau[i][j]);
                                           52          
                                           53         for (int i = 0; i < premiere_dimension; i++)
                                           54                 free(tableau[i]);
                                           55          
                                           56         free(tableau);
                                          



                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            8 août 2019 à 22:19:14

                                            Bonjour,

                                            Le code est correct, j'aurais juste simplifié un peu les libérations

                                               for ( int i = 0 ; i < premiere_dimension ; i++ )
                                               {
                                                   for ( int j = 0 ; j < deuxieme_dimension ; j++ )
                                                       free( tableau[i][j] );
                                                   free( tableau[i] );
                                               }       
                                               free( tableau );
                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            En recherche d'emploi.

                                              9 août 2019 à 10:10:45

                                              Bonjour,

                                              @PierreBoutier1 : pense à subdiviser ton code en fonctions, c'est une bonne pratique à prendre (idéalement une fonction doit faire une seul chose (que l'on peut deviner à son nom), mais le faire bien) .:)

                                              C'est ce que l'on appelle le S.R.P : Single Responsability Principle

                                              -
                                              Edité par Warren79 9 août 2019 à 10:12:33

                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              Mon site web de jeux SDL2 entre autres : https://www.ant01.fr

                                                9 août 2019 à 15:18:28

                                                ok Warren c'est noté je clos le sujet je pense que l'on a fait le tour merci encore pour toutes vos précisions
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  10 août 2019 à 6:50:26

                                                  Dalfab a écrit:

                                                  Bonjour,

                                                  Je dirais qu'il existe au moins trois formes possibles. Je prend l'exemple de 3 dimensions :
                                                  - le tableau de tableaux de tableaux : Type*** tableau1 qui va demander de nombreuses allocations.
                                                  - le tableau linéarisé : Type* tableau2 qui ne demande qu'une seule allocation. Si les dimensions sont des constantes il a un équivalent Type tableau3[NB_COL*NB_LIG*NB_PROF].
                                                  - le tableau à 3 dimensions : Type* tableau4[NB_LIG][NB_COL] qui lui aussi ne demande qu'une allocation mais exige que les 2 premières dimensions soient des constantes compilation.


                                                  On peut aussi avoir fromage et dessert, avec une seule allocation par dimension.

                                                  Exemple, pour un tableau 2d de NBR x NBC  entiers

                                                  • int * data = malloc (NBR * NBC * sizeof(int))  pour les éléments
                                                  • int ** array = malloc (NBR * sizeof (int *))  pour les pointeurs de ligne
                                                  Et boucle pour remplir array:
                                                  for (int r=0; r<NBR; r++) {
                                                     array[r] = data + r * NBC;
                                                  }
                                                  Ce qui permet d'utiliser la notation array[r][c], tout en conservant la localité des données et en évitant l'overhead d'une allocation par ligne.
                                                  En fait, par rapport à la linearisation  ça revient à précalculer les positions de début des lignes, et à échanger une multiplication contre une indexation.
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

                                                  Allocation dynamique d'un tableau à deux dimensios

                                                  × 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