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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    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 confirmé
    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
    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));
         ....
      }

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    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 confirmé
    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
    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;
    }

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    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 confirmé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    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);
    }

+ 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