IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Allocation dynamique d'un tableau 1D dans une structure de données en C


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut Allocation dynamique d'un tableau 1D dans une structure de données en C
    Bonjour,

    Je voudrais savoir si quelqu'un peut m'aider à allouer dynamiquement de la mémoire à un tableau 1D (tab1) se trouvant dans une structure de données. J'arrive à le faire avec tab2 et ça marche bien, j'ai compris le principe dans ce cas, cependant je n'arrive pas avec tab1. Comment procéder?

    la variable N définie ici avec
    n'est en principe pas connue et doit être entrée par l'utilisateur comme pour dim.

    Voici mon code source :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
    #define N 10
     
    typedef struct point point;
    struct point
    {
     
    double x;
    double y;
    double z;
    int tab1[N];
    };
     
    point *tab2;
     
     
     
    int main(int argc, char *argv[])
    {
    int dim;
    int k,k1;
     
    	printf("Entrez la dimension du tableau tab2\n");
    	scanf("%d",&dim);
    	printf("%d\n",dim);
     
    	/* Allocation dynamique du tableau tab2 */
     
        tab2=calloc(dim,sizeof(struct point));
     
    	if(tab2==NULL){printf("Allocation tab2 impossible\n");exit(-1);}
     
    	   /* Remplissage du tableau tab2 */
    	   for(k=0;k<dim;k++)
    	   {
    	       tab2[k].x=(double)k+1;
    		   tab2[k].y=2.0*(double)k+rand();
    		   tab2[k].z=3.0*(double)k+rand();
    	   }
     
    	   /* Affichage du tableau tab2 */
    	   k=0;
    	   do{
    	     printf("%lf %lf %lf \n",tab2[k].x,tab2[k].y,tab2[k].z);
    		k++;
    	   }while(k<dim);
     
    	    /* Remplissage de tab1 */
    		for(k=0;k<dim;k++){
    			for(k1=0;k1<N;k1++)
    			{
    				tab2[k].tab1[k1]+=1;
    			}
    		}
     
    	    /* Affichage de tab1*/
    		for(k=0;k<dim;k++){
    			for(k1=0;k1<N;k1++)
    			{
    				 printf("tab2[%d].tab1[%d]=%d \n",k,k1,tab2[k].tab1[k1]);
    			}
    			printf("\n");
    		}
     
     
        /* Liberation de la memoire allouee au tab2 */	 
    	if(tab2!=NULL){free(tab2);}
    	tab2=NULL;
     
    	return EXIT_SUCCESS;
     
    }
    D'avance merci pour votre aide.

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    C'est exactement pareil que pour tab2 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    struct point
    { 
      double x;
      double y;
      double z;
      int *tab1;
    };
    .....  
      for(k=0;k<dim;k++)
      {
         tab2[k].x=(double)k+1;
         tab2[k].y=2.0*(double)k+rand();
         tab2[k].z=3.0*(double)k+rand();
         tab2[k].tab1 = malloc(N*sizeof(int));
         ....
      }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    Merci beaucoup pour ton aide, ça marche bien.
    Cependant, j'ai rajouté un test d'allocation de mémoire puis la libération à la fin des calculs de la mémoire allouée si quelqu'un peut relire le code ci-dessous et me donner son point de vue. Aucun problème à la compilation et à l’exécution...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
     
    typedef struct point point;
    struct point
    {
     
    double x;
    double y;
    double z;
    int *tab1;
    };
     
    point *tab2;
     
     
     
    int main(int argc, char *argv[])
    {
    int dim,n;
    int k,k1,e=0;
     
    	printf("Entrez la dimension du tableau tab1\n");
    	scanf("%d",&n);
    	printf("%d\n",n);
     
    	printf("Entrez la dimension du tableau tab2\n");
    	scanf("%d",&dim);
    	printf("%d\n",dim);
     
     
    	/* Allocation dynamique du tableau tab2 */
     
        tab2=calloc(dim,sizeof(struct point));
     
    	if(tab2==NULL){printf("Allocation tab2 impossible\n");exit(-1);}
     
    	   /* Remplissage du tableau tab2 */
    	   for(k=0;k<dim;k++)
    	   {
    	       tab2[k].x=(double)k+1;
    		   tab2[k].y=2.0*(double)k+rand();
    		   tab2[k].z=3.0*(double)k+rand();
    		   tab2[k].tab1=calloc(n,sizeof(int));
    		   if(tab2[k].tab1==NULL){printf("Allocation tab1 impossible\n");e+=1;}
    	   }
     
    	   /* Affichage du tableau tab2 */
    	   k=0;
    	   do{
    	     printf("%lf %lf %lf \n",tab2[k].x,tab2[k].y,tab2[k].z);
    		k++;
    	   }while(k<dim);
     
     
     
     
     
    	    /* Remplissage de tab1 */
    		for(k=0;k<dim;k++){
    			for(k1=0;k1<n;k1++)
    			{
    				tab2[k].tab1[k1]+=1;
    			}
    		}
     
    	    /* Affichage de tab1*/
    		for(k=0;k<dim;k++){
    			for(k1=0;k1<n;k1++)
    			{
    				 printf("tab2[%d].tab1[%d]=%d \n",k,k1,tab2[k].tab1[k1]);
    			}
    			printf("\n");
    		}
     
     
    	 /* Liberation memoire tableau tab1 */
    	 for(k=0;k<dim;k++)
    	 {
    			if(tab2[k].tab1!=NULL){free(tab2[k].tab1);tab2[k].tab1=NULL;}
    	 }
     
        /* Liberation de la memoire allouee au tab2 */	 
    	if(tab2!=NULL){free(tab2);}
    	tab2=NULL;
     
    	return EXIT_SUCCESS;
     
    }
    Merci

  4. #4
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Quelques critiques constructives :

    - Toujours sur la question d'allocation dynamique, c'est bien de prévoir les tests de validité et la libération de la mémoire allouée mais

    -- la réponse à un échec d'allocation d'un tab1 est insuffisante : affichage d'un message et continuation du programme ce qui conduit à un plantage lors de tab2[k].tab1[k1]+=1. Il est préférable de tout nettoyer (libérer les tab1 déjà alloués et tab2) et sortir proprement du programme.

    -- Il faut être cohérent : if(tab2!=NULL){free(tab2);} .
    Pourquoi ce test tab2!=NULL ? Si tab2 == NULL, le programme a déjà planté avant dans une des boucles de remplissage/affichage ou dans le code de libération de tab1. Heureusement ce cas ne peut se produire puisqu'on serait sorti du programme plus tôt mais du coup, le programmeur n'a pas l'air de bien maîtriser ses allocations/désallocations.
    Accessoirement, on peut faire free(NULL) sans problèmes.

    - Pourquoi tab2 est-il une variable globale (Pouah) ?

    - Il manque la séquence d'initialisation du générateur aléatoire

    - Ne pas faire de transtypages inutiles qui alourdissent le code et amènent le lecteur à se poser inutilement des questions

    - Ne pas faire d'include inutile (math.h)

    - Surtout, soigner la présentation du code (indentation, position des { et }, sauts de lignes inutiles), il est difficile à lire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    #include <stdio.h>
    #include <stdlib.h>
    /*---------------------------------------*/  
    typedef struct point point;
    struct point
    { 
       double x;
       double y;
       double z;
       int *tab1;
    }; 
    /*---------------------------------------*/ 
    int main(void)
    {
       point *tab2;
       int dim,n;
       int k,k1,e=0;   // A quoi sert e ????
     
       printf("Entrez la dimension du tableau tab1\n");
       scanf("%d",&n);
       printf("%d\n",n);
       printf("Entrez la dimension du tableau tab2\n");
       scanf("%d",&dim);
       printf("%d\n",dim);
     
       /* Allocation dynamique du tableau tab2 */ 
       tab2=calloc(dim,sizeof(struct point));
       if(tab2==NULL)
       {
          printf("Allocation tab2 impossible\n");
          exit(-1);
       }
     
       /* Remplissage du tableau tab2 */
       for(k=0;k<dim;k++)
       {
          tab2[k].x = k+1;
          tab2[k].y = 2.0*k+rand();
          tab2[k].z = 3.0*k+rand();
          tab2[k].tab1 = calloc(n,sizeof(int));
          if(tab2[k].tab1==NULL)           
          {
             printf("Allocation tab1 impossible\n");// Code à revoir
             e+=1;
          }
       }
     
       /* Affichage du tableau tab2 */
       k=0;
       do                                // Pourquoi pas ici une boucle for qui semble naturelle ?
       {
          printf("%lf %lf %lf \n",tab2[k].x,tab2[k].y,tab2[k].z);
          k++;
       }while(k<dim);
     
       /* Remplissage de tab1 */
       for(k=0;k<dim;k++)
          for(k1=0;k1<n;k1++) tab2[k].tab1[k1]+=1;
     
       /* Affichage de tab1*/
       for(k=0;k<dim;k++)
       {
          for(k1=0;k1<n;k1++) printf("tab2[%d].tab1[%d]=%d \n",k,k1,tab2[k].tab1[k1]);
          printf("\n");
       }
     
       /* Liberation memoire tableau tab1 */
       for(k=0;k<dim;k++) free(tab2[k].tab1);
     
       /* Liberation de la memoire allouee au tab2 */	 
       free(tab2);
       return EXIT_SUCCESS;
    }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    Merci pour tes remarques et critiques.

    Je n'étais pas suffisamment claire sur l'énoncé de mon programme ou plutôt sur la raison d'être de mon code.

    Ce bout de code ne traite aucun problème réel, le but était simplement de pouvoir allouer dynamiquement de la mémoire à deux tableaux distincts se trouvant à différents endroits dans le projet. Je comprends que l'utilisation d'une variable global te dégoûte puisque pratiquement tous les cours de programmation le déconseille. Les valeurs attribuées à tab2 n'ont aucune importance, j'aurai pu affecter autre chose à la place des rand() mais je suis d'accord sur toi pour le principe. Et merci d'ailleurs pour cette rigueur...et pour ton analyse complète de ce code.

    Je vais le modifier notamment pour le traitement du problème en cas d'échec d'allocation et je proposerai une nouvelle version.

    Merci !

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    Bonjour,

    Je propose une version revue et corrigée (code ci-dessous) suite à vos remarques et conseils. Celle-ci compile et fonctionne sans problème mais il y a peut être des choses à améliorer... Vos critiques sont toujours les bienvenues si quelque chose vous choque dans ce bout de code, rappelons que ma question initiale se portant sur l'allocation dynamique d'un tableau dans une structure de données.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    #include <stdio.h>
    #include <stdlib.h>
    /*---------------------------------------*/  
    typedef struct point point;
    struct point
    { 
       double x;
       double y;
       double z;
       int *tab1;
    }; 
    /*---------------------------------------*/ 
    int main(void)
    {
       point *tab2;
       int dimtab1,dimtab2;
       int k,k1;
     
       printf("Entrez la dimension du tableau tab1\n");
       scanf("%d",&dimtab1);
       printf("%d\n",dimtab1);
       printf("Entrez la dimension du tableau tab2\n");
       scanf("%d",&dimtab2);
       printf("%d\n",dimtab2);
     
       /* Allocation dynamique du tableau tab2 */ 
       tab2=calloc(dimtab2,sizeof(struct point));
       if(tab2==NULL)
       {
          printf("Allocation tab2 impossible\n");
          exit(EXIT_FAILURE);
       }
     
    	   /* Remplissage du tableau tab2 */
    	   for(k=0;k<dimtab2;k++)
    	   {
    		  tab2[k].x = k+1;
    		  tab2[k].y = 2.0;
    		  tab2[k].z = 3.0;
     
    			   if ((tab2[k].tab1= calloc(dimtab1, sizeof(int))) == NULL )
    			   {
    				   if(k>0)
    				   {
    					  for(k1=(k-1);k1>=0;k1--)
    					  {
    						free(tab2[k1].tab1);
    					  }
    					  free(tab2);
    					  tab2=NULL;
    					  break;
     
    				   }
     
    			  }
     
    	   }
     
     
       /* Liberation memoire tableau tab1 */
       for(k=0;k<dimtab2;k++) free(tab2[k].tab1);
     
       /* Liberation de la memoire allouee au tab2 */	 
       free(tab2);
       return (EXIT_SUCCESS);
    }

  7. #7
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Il y a une erreur : si il y a une erreur d'allocation pour tab2[k].tab1, le programme libère bien ce qui a été alloué mais continue et recommence la libération plus bas -> Plantage.

    Dans la correction, faire attention à ce qui arrivera pour la libération de tab2 si l'erreur d'allocation a lieu pour k=0 : il ne suffit pas de remplacer le break par un return, il faut réordonner un peu le code, du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    ....
       /* Remplissage du tableau tab2 */
       for(k=0;k<dimtab2;k++)
       {
    ....
         if ((tab2[k].tab1= calloc(dimtab1, sizeof(int))) == NULL )
         {
             for(k1=k-1;k1>=0;k1--)free(tab2[k1].tab1); //le if(k>0) est inutile
             free(tab2);
             return EXIT_FAILURE;
         }
       } 
       /* Liberation memoire tableau tab1 */
       for(k=0;k<dimtab2;k++) free(tab2[k].tab1);
     
       /* Liberation de la memoire allouee au tab2 */	 
       free(tab2);
       return (EXIT_SUCCESS);
    }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    Merci pour ta remarque, en effet, sortir avec le break et ré-libérer à la fin du programme conduira droit à un plantage...

    J'ai réorganisé le programme comme ci-dessous en supprimant ce qui n'est finalement pas très utile pour l'objectif visé ici.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    #include <stdio.h>
    #include <stdlib.h>
    /*---------------------------------------*/  
    typedef struct point point;
    struct point
    { 
       double x;
       double y;
       double z;
       int *tab1;
    }; 
    /*---------------------------------------*/ 
    int main(void)
    {
       point *tab2;
       int dimtab1,dimtab2;
       int k,k1;
     
       printf("Entrez la dimension du tableau tab1\n");
       scanf("%d",&dimtab1);
       printf("%d\n",dimtab1);
       printf("Entrez la dimension du tableau tab2\n");
       scanf("%d",&dimtab2);
       printf("%d\n",dimtab2);
     
       /* Allocation dynamique du tableau tab2 */ 
       tab2=calloc(dimtab2,sizeof(struct point));
       if(tab2==NULL)
       {
          printf("Allocation tab2 impossible\n");
          exit(EXIT_FAILURE);
       }
     
     
    	 /* Allocation dynamique du tableau tab1*/
     
    		for(k=0;k<dimtab2;k++)
    	   { 
     
    			   if ((tab2[k].tab1= calloc(dimtab1, sizeof(int))) == NULL )
    			   {
     
    					  for(k1=(k-1);k1>=0;k1--)
    					  {
    						free(tab2[k1].tab1);
    					  }
    					  free(tab2);
    					  tab2=NULL;
    					  fprintf(stdout,"Probleme d'allocation memoire a la ligne %d du fichier %s \n",(__LINE__),(__FILE__));
    					  return (EXIT_FAILURE);
     
    			  }
     
    	   }
     
     
       /* Liberation memoire tableau tab1 */
       for(k=0;k<dimtab2;k++) free(tab2[k].tab1);
     
       /* Liberation de la memoire allouee au tab2 */	 
       free(tab2);
       return (EXIT_SUCCESS);
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Tableau unidimensionnel dans une structure
    Par Helices dans le forum C++/CLI
    Réponses: 7
    Dernier message: 30/06/2014, 14h41
  2. Réponses: 11
    Dernier message: 09/02/2010, 11h42
  3. Réponses: 11
    Dernier message: 18/08/2008, 16h38
  4. Réponses: 4
    Dernier message: 11/02/2008, 18h03
  5. Réponses: 7
    Dernier message: 21/12/2005, 16h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo