Menu

Tableau structures argument de fonctions :retour [Résolu]

getudir78 10 Messages postés vendredi 3 janvier 2014Date d'inscription 1 juillet 2018 Dernière intervention - 13 juin 2018 à 16:02 - Dernière réponse : [Dal] 4754 Messages postés mercredi 15 septembre 2004Date d'inscriptionContributeurStatut 23 octobre 2018 Dernière intervention
- 14 juin 2018 à 23:25
/*
le programme compile et s'execute partiellement

lorsque allocation de memoire et initialisation des champs
sont realisees directement dans le main, ce programme fonctionne bien

lorsque allocation de memoire et initialisation des champs
sont realisees a l'aide d'une fonctions, tout semble bien se passer dans la fonction
mais apres cela, le tableau de structures n'est pas accessible dans le main

merci de m'aider a trouver l'erreur
  • /

#include <stdio.h>
#include<stdlib.h>
typedef struct personne
{
  char nom[15];
  int age;
  float poids;
} mapersonne;

void creer_tab (int dim, mapersonne *tab) {
 /*mmm initialise le tableau de structures */
 int i;
 printf("char = %d\n",sizeof(char));
 printf("int = %d\n",sizeof(int));
 printf("dim = %d\n",sizeof(float));
 printf("mapersonne sizeof = %d\n", sizeof(mapersonne));
 //
 tab = malloc(dim*sizeof(mapersonne));
 
 i = 0;
 while ( i < dim) {
  printf("donnez un nom - un age - un poids\n");
  scanf("%s", tab[i].nom);
  scanf("%d", &(tab[i].age));
  scanf("%f", &(tab[i].poids));
  printf("dans fonction creer_tab : nom = %s age = %d poids = %f\n",tab[i].nom, tab[i].age, tab[i].poids);
  i++;
 }
 return ;
}

int main() {
 int nb_pers, i;
 // pointeur defini pour l'allocation dynamique de memoire
 mapersonne *tab_pers_1 = NULL;
 mapersonne *tab_pers_2 = NULL;
 //
 printf ("nombre de personnes a definir ?\n");
 scanf("%d", &nb_pers);
 //
 // debut creation tab_pers_1 directement dans main() - tout fonctionne parfaitement
 printf("debut de l'initialisatio du tableau de structures directement dans main()\n");
 tab_pers_1 = malloc(nb_pers*sizeof(mapersonne));
 //
 i = 0;
 while ( i < nb_pers) {
  printf("donnez un nom - un age - un poids\n");
  scanf("%s", tab_pers_1[i].nom);
  scanf("%d", &(tab_pers_1[i].age));
  scanf("%f", &(tab_pers_1[i].poids));
  i++;
 }
 // impression de valeurs definies ci-dessus
 for (int i = 0;i<nb_pers;i++) {
  printf("nom : %s age = %d poids =  %f\n",tab_pers_1[i].nom, tab_pers_1[i].age, tab_pers_1[i].poids);
 }
 printf("fin de l'initialisation du tableau de structures directement dans main()\n");
 // fin creation tab_pers_1 directement dans main() - tout fonctionne parfaitement
 //
 //debut creation tab_pers_2 par la fonction creer_tab - probleme :
 // les valeurs initialsees dans creer_tab(...) ne sont pas connues dans fonction creer_tab
 printf("\ndebut de l'initialisation du tableau de structures par la fonction creer_tab\n");
 //
 creer_tab (nb_pers, tab_pers_2);
 //
 //impression des valeurs retournees dans le main()
 // dans l'etat actuel du programme, 
 for (int i = 0;i<nb_pers;i++) {
  printf(" valeurs retournees de creer_tab personne numero : %d nom : %s",i, tab_pers_2[i].nom);
  printf(" age = %d", tab_pers_2[i].age);
  printf(" poids = %f\n",tab_pers_2[i].poids);
 }
 printf("fin de l'initialisation du tableau de structures par la fonction creer_tab\n");
 //fin creation tab_pers_2 par la fonction  - probleme :
 // les valeurs initialsees dans creer_tab(...) ne sont pas commues dans le main
 //
 return 0;
}
Afficher la suite 

Votre réponse

4 réponses

[Dal] 4754 Messages postés mercredi 15 septembre 2004Date d'inscriptionContributeurStatut 23 octobre 2018 Dernière intervention - Modifié par [Dal] le 14/06/2018 à 11:10
0
Merci
Salut getudir78,

Dans main
mapersonne *tab_pers_2 = NULL;
, tab_pers_2 est une variable pointeur et la valeur contenue par cette variable est NULL.

Or, tu passes cette variable à
creer_tab()
.

Comme tout passage de variable, en C, le passage d'une variable opère une copie de cette variable, sur laquelle travaille la fonction.

Donc, dans ta fonction
creer_tab()
, lorsque tu alloues de la mémoire et que tu ranges l'adresse mémoire du bloc alloué, tu ranges l'adresse dans une autre variable pointeur (la copie), et donc la variable pointeur déclarée dans main() n'est pas modifiée et continue de pointer vers NULL.

Dal
[Dal] 4754 Messages postés mercredi 15 septembre 2004Date d'inscriptionContributeurStatut 23 octobre 2018 Dernière intervention - 14 juin 2018 à 10:45
Pour résoudre ce problème, tu pourrais changer ton prototype et passer un pointeur sur un pointeur sur struct, et ensuite déréférencer correctement ce pointeur.

Cependant, puisque tu alloues la mémoire dans ta fonction, le passage du pointeur n'a pas trop d'intérêt, et tu te compliques vraiment la vie.

Alors, une façon beaucoup plus simple de faire est de passer juste le nombre de personnes à créer et que
creer_tab()
retourne un pointeur sur mapersonne.

Quelque chose comme cela :

#include <stdio.h>
#include <stdlib.h>

typedef struct personne {
    char nom[15];
    int age;
    float poids;
} mapersonne;

mapersonne * creer_tab(int dim) {
    int i = 0;
    mapersonne * tab = NULL;

    tab = malloc(dim * sizeof(mapersonne));
    for (i = 0; i < dim; i++) {
        printf("donnez un nom - un age - un poids\n");
        scanf("%s", tab[i].nom);
        scanf("%d", &tab[i].age);
        scanf("%f", &tab[i].poids);
    }

    return tab;
}

int main(void) {
    int nb_pers, i;
    mapersonne * tab = NULL;
    
    printf ("nombre de personnes a definir ?\n");
    scanf("%d", &nb_pers);

    tab = creer_tab(nb_pers);

    for (i = 0; i < nb_pers; i++) {
        printf(" valeurs retournees de creer_tab personne "
                "numero : %d nom : %s", i, tab[i].nom);
        printf(" age = %d", tab[i].age);
        printf(" poids = %f\n", tab[i].poids);
    }
    free(tab);

    return 0;
}

Une autre façon simple de faire serait de garder ton prototype
void creer_tab (int dim, mapersonne *tab)
, mais d'opérer l'allocation mémoire dans
main()
et donc de laisser à la fonction appelante de
creer_tab()
la responsabilité d'allouer la mémoire.

Il y a une certaine logique à cette dernière approche, car la fonction appelante est aussi responsable de la libération de la mémoire (le
free()
, que tu avais d'ailleurs omis dans ton code).

Dal
Merci pour tes explications limpides. J'ai implémenté la première démarche et compilation comme exécution se passent parfaitement bien.
Mon problème est donc résolu!
[Dal] 4754 Messages postés mercredi 15 septembre 2004Date d'inscriptionContributeurStatut 23 octobre 2018 Dernière intervention - 14 juin 2018 à 23:25
Génial, je suis content !

En ce qui me concerne, la première approche me rend un peu nerveux ;-)

Je lui préfère la dernière approche, qui permet de dissocier l'allocation mémoire de l'usage de l'espace alloué par la fonction. Cela me permet de mettre, dans la même fonction appelante, le
malloc()
et le
free()
... et cela me rassure de pouvoir, autant que possible, voir les deux dans la même fonction :-)
Commenter la réponse de [Dal]