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 :

Problème de Pointeur avec une structure pointée


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut Problème de Pointeur avec une structure pointée
    Bonjour

    Voila, dans le but de mes cours, je dois essayer de faire de l'allocation dynamique d'un pointeur sur une structure pointée... enfin si je m'exprime bien

    Voici le code

    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
     
     
    // Pointeur Structure.cpp*: définit le point d'entrée pour l'application console.
    //
     
    #include "stdafx.h"
    #include <stdlib.h>
    #include <string.h>
     
    #define MAX 2
     
     
    typedef struct personne
    {
     char nom[40];
     char sexe;
     int age;
     
    } ELEVE;
     
    void ajouterEleve (ELEVE **, int *);
    void afficherEleve (ELEVE **, int *);
     
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	 ELEVE ** ptab_eleve=NULL,*p;
    	 char nomT [40];
    	 char **pnomT;
     
     
    	int taille=1,i=0;
     
     //ajouterEleve(ptab_eleve,&taille);
     
    // printf("\n taille: %d\n",taille);
    	ptab_eleve=(ELEVE**) malloc(sizeof (ELEVE));
    	p=(ELEVE*) malloc(sizeof (ELEVE));
    	strcpy(p->nom,"gaston");
    	if( ptab_eleve == NULL )
    {
         printf("Allocation impossible");
    }
    	strcpy((*(ptab_eleve)+i)->nom, p->nom); /* Voila mon problème car je ne sais pas comment je dois faire pour accéder au paramètre nom de ma structure ELEVE avec ptab_eleve*/
     
     
     
     
    // afficherEleve (ptab_eleve,&taille);
     
     
    /* for (i=0;i<taille;i++)
     {
         free(ptab_eleve[i]);
         
     } */
     
    	return 0;
    }
    si quelqu'un pouvait éclairer ma lanterne, ce sera sympa car la, je cale

    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
    Si je comprend (?), il faut un tableau d'ELEVE alloué par allocation dynamique. Celle-ci va renvoyer l'adresse du premier élément du tableau alloué, soit un type ELEVE*

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ELEVE * ptab = malloc(N* sizeof *ptab);
    if(ptab!= NULL)...
    où N est le nombre d'ELEVE dans le tableau

    Les différents ELEVE du tableau sont accessible par ptab[i] et leur nom par ptab[i].nom (i=0..N-1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy(ptab[i].nom,"gaston");

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    heu... à la base dans mon code, j'ai ELEVE ** ptab_eleve = NULL;

    quand je lis l'exemple que tu donnes, il n'y est plus... mon code serait il si mauvais :-s

    car oui, je dois allouer mon tableau de manière dynamique d'ou une double étoile

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 041
    Points
    33 041
    Billets dans le blog
    4
    Par défaut
    Non c'est la "première étoile" qui indique qu'il s'agit d'un pointeur, et que tu souhaites utiliser comme tableau.
    La seconde étoile indique que son contenu sera des ELEVE*

    Et dans ton cas, l'utilisation d'un pointeur sur pointeur, la double étoile, traduit un manque de connaissance des pointeurs, vu l'utilisation que tu souhaites. Un tableau dynamique d'objet te suffira. Sinon, tu devras aussi allouer chaque ELEVE* contenu dans celui-ci.

    D'ailleurs,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ELEVE** ptab_eleve=(ELEVE**) malloc(sizeof (ELEVE));
    	ELEVE* p=(ELEVE*) malloc(sizeof (ELEVE));
    tu alloues 2 variables qui n'ont pas le même type avec la même taille.
    Rien ne te choque ?

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    Mince, au départ, j'avais mis ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
          ELEVE** ptab_eleve=(ELEVE**) malloc(sizeof (ELEVE*));
    	ELEVE* p=(ELEVE*) malloc(sizeof (ELEVE));
    mais je supose que cela ne change pas grand chose...

    sinon pour répondre à la question pourquoi une double étoie, c'est mon prof qui me l'a demandé :/

    car par la suite, je dois utiliser la fonction realloc pour agrandir dynamiquement mon tableau de pointeurs.

  6. #6
    Membre éclairé Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Points : 790
    Points
    790
    Par défaut
    Citation Envoyé par misterlagaffe Voir le message
    mais je supose que cela ne change pas grand chose...
    Dans ce code, tu n'alloues qu'un seul pointeur dans ton tableau de pointeur ptab_eleve.

    Et si ce dernier exemple que tu donne change parceque il y a une différence entre sizeof(ELEVE) et sizeof(ELEVE *). L'un te donne la taille d'une structure élève, l'autre te donne la taille d'un pointeur vers une telle structure.

    Citation Envoyé par Bousk
    Un tableau dynamique d'objet te suffira
    C'est peut-être un exercice pédagogique pour apprendre les pointeurs de pointeurs.

    Si tu veux donc travailler avec un tableau de pointeur il faut plutot faire un truc comme cela :
    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
     
    /* allocation de ton tableau de pointeurs */
    ptab_eleve = (ELEVE**) malloc(N * sizeof (ELEVE *));
    if(ptab_eleve == NULL)
    {
         printf("Allocation impossible");
    }
     
    /* allocation d'un eleve */
    p = (ELEVE*) malloc(sizeof (ELEVE));
    if(p == NULL)
    {
         printf("Allocation impossible");
    }
    /* renseignement des champs de la structure élève */
    strcpy(p->nom,"gaston");
    p->age = 12;
    /* etc */
     
    /* on met l'élève dans le tableau par une simple affectation de pointeur. */
    /* i < N */
    ptab_eleve[i] = p;

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    Effectivement, c'est bien çà Valefor
    mais helas, quand j'applique çà avec une fonction, l'affichage ne fonctionne mais bon, je pense qu'un exemple vaut mieux que du blabla :-)

    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
    // Pointeur Structure.cpp*: définit le point d'entrée pour l'application console.
    //
     
    #include "stdafx.h"
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
     
    #define MAX 2
     
     
    typedef struct personne
    {
    	char nom[40];
    	char sexe;
    	int age;
     
    } ELEVE;
     
    void ajouterEleve (ELEVE **, int *);
    void afficherEleve (ELEVE **, int *);
     
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	ELEVE ** ptab_eleve=NULL,*p;
     
     
     
    	int taille=1,i=0;
     
    	ajouterEleve(ptab_eleve,&taille);
     
    	printf("(main)nom : %s\n", ptab_eleve[i]->nom); // Ca plante
     
     
    	return 0;
    }
     
    void ajouterEleve (ELEVE ** ptab, int *nb)
    {
    	int i=0;
    	char reponse;
    	ELEVE *p;
     
     
    		/* allocation de ton tableau de pointeurs */
    		ptab = (ELEVE**) malloc(5 * sizeof (ELEVE *));
    		if(ptab == NULL)
    		{
    			printf("Allocation impossible");
    		}
     
    		/* allocation d'un eleve */
    		p = (ELEVE*) malloc(sizeof (ELEVE));
    		if(p == NULL)
    		{
    			printf("Allocation impossible");
    		}
    		/* renseignement des champs de la structure élève */
    		strcpy(p->nom,"gaston");
    		p->age = 12;
    		/* etc */
     
    		/* on met l'élève dans le tableau par une simple affectation de pointeur. */
    		/* i < N */
    		ptab[i] = p;		
    		printf("--------------------------------------------------------\n");
     
    		printf("(fonction)nom: %s\n",ptab[i]->nom);
     
    		free(p);
     
     
     
     
    }

  8. #8
    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
    Apparemment, d'après les échanges précédents, on te demanderait de faire un tableau de pointeurs sur ELEVE qui devrait être redimensionné si nécessaire. Je me demande si ce n'est pas plutôt un tableau d'ELEVE au vu du prototype de ajouterEleve() que tu envisages. Je vais toutefois faire une description pour un tableau de pointeurs, elle est facilement adaptable en cas de tableau d'ELEVE.

    L'adresse du début du tableau de pointeurs sera donc placée dans une variable du type ELEVE** .
    L'ajout d'un ELEVE dans ce tableau se fera par :
    1- si le tableau possède une case vide (un pointeur NULL) alors ajouter le nouvel ELEVE à cette place
    2- si toutes les cases sont utilisées, agrandir le tableau et ajouter le nouvel ELEVE.
       Attention cette opération peut modifier l'adresse de départ du tableau de pointeurs et modifie son nombre d'éléments.
    la fonction ajouterEleve() doit donc connaitre :
    - l'adresse du premier élément du tableau (de pointeurs)
    - le nombre actuel d'éléments de ce tableau (nécessaire pour faire le redimensionnement)
    - l'adresse de l'ELEVE à ajouter au tableau 
    elle doit pouvoir modifier
    - l'adresse du premier élément du tableau de pointeurs en cas de redimensionnement
    - le nombre d'éléments de ce tableau en cas de redimensionnement
    ses paramètres sont donc
    - l'adresse du pointeur (contenant l'adresse du premier élément du tableau) pour pouvoir modifier le pointeur
    - l'adresse de l'entier (contenant le nombre d'éléments) pour pouvoir modifier sa valeur
    - l'adresse de l'ELEVE à ajouter au tableau
    elle peut avantageusement renvoyer un indicateur indiquant que l'insertion a réussi ou échoué (reallocation réussie ou en échec)

    Son prototype serait alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int ajouterEleve( ELEVE *** tab, int * n, ELEVE * eleve);
    Elle serait appelée de la façon suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ELEVE ** tableau = NULL;
    int ntab = 0;
    // création d'un ELEVE à l'adresse p : p = malloc(sizeof(ELEVE); + initialisation
    if (!ajouterEleve(&tableau,&ntab,p) printf("Erreur d'allocation");
    Le déroulement de la fonction int ajouterEleve(ELEVE *** tab,int *n, ELEVE * eleve) :
    -  Chercher si il y a une place libre dans le tableau débutant en *tab et ayant *n éléments :
        Chercher de i = 0 à i < *n si il y a un pointeur NULL dans le tableau.
    -  Si oui, mettre eleve à cette place, retourner 1
    -  Si non, agrandir le tableau de N (>0) cases (realloc()).
         -  En cas d'échec retourner 0
         -  En cas de succès 
              - mettre eleve en *n et mettre à NULL les pointeurs de *n+1 à *n+N-1
              - Copier la nouvelle valeur du nombre d'éléments *n+N dans *n
              - Copier la nouvelle adresse de départ du tableau dans *tab
              - retourner 1

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 041
    Points
    33 041
    Billets dans le blog
    4
    Par défaut
    N'ayant pas l'énonce complet, on ne peut que faire des suppositions, mais diogene a totalement raison.

    Par contre, pour le code en lui-même, il y a des lacunes.

    Dans ton main
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ajouterEleve(ptab_eleve,&taille);
    ptab_eleve est NULL à ce moment-là. Attention à ce que ça peut entraîner.

    Ensuite, et plus grave amha
    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
    void ajouterEleve (ELEVE ** ptab, int *nb)
    {
    	int i=0;
    	char reponse;
    	ELEVE *p;
     
    		/* allocation de ton tableau de pointeurs */
    		ptab = (ELEVE**) malloc(5 * sizeof (ELEVE *));
    		if(ptab == NULL)
    		{
    			printf("Allocation impossible");
    		}
     
    		/* allocation d'un eleve */
    		p = (ELEVE*) malloc(sizeof (ELEVE));
    		if(p == NULL)
    		{
    			printf("Allocation impossible");
    		}
    		/* renseignement des champs de la structure élève */
    		strcpy(p->nom,"gaston");
    		p->age = 12;
    		/* etc */
     
    		/* on met l'élève dans le tableau par une simple affectation de pointeur. */
    		/* i < N */
    		ptab[i] = p;		
    		printf("--------------------------------------------------------\n");
     
    		printf("(fonction)nom: %s\n",ptab[i]->nom);
     
    		free(p);
    }
    Tu commences par allouer ptab avec 5 cases, potentiellement tu perds ce qu'il contenait auparavant : fuite mémoire.
    puis tu crées un ELEVE* que tu places en ptab[0]; 2° source de fuite mémoire : tu perds l'ancien contenu de ptab[0]

    Commencer par réviser son cours sur les pointeurs semble être une bonne idée.
    Pars d'un code plus simple, et complexifie-le au fur et à mesure.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    Effectivement j'ai du mal à le maitriser ce pointeur de pointeur. Avec un pointeur simple, je n'ai pas trop de soucis mais là, j'avoue, je suis perdu.

    en fait, j'ai fait cette exercice de manière simple à la base.

    Cela ressemble à ca : Attention: je n'ai fait aucune vérification, c'est juste savoir utiliser les structures qu'on nous demande.

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define MAX 3
     
    typedef struct personne
    {
     char nom[40];
     char sexe;
     int age;
     
    } ELEVE;
     
     
     
    int main(int argc, char *argv[])
    {
     ELEVE toto [MAX];
     int i=0;
     
     for (i=0;i<MAX;i++)
     {
         printf("Eleve N : %d\n",i+1);
         printf("Veuillez introduire un nom svp? ");
         gets(toto[i].nom);
         fflush(stdin);
         printf("Veuillez introduire le sexe de l'eleve : ");
         scanf("%c",&toto[i].sexe);
         fflush(stdin);
         printf("Veuillez introduire l'age de l'eleve : ");
         scanf("%d",&toto[i].age);
         fflush(stdin);
         printf("--------------------------------------------------------\n");  
     
     }
     
     system ("CLS");
     
     for (i=0;i<MAX;i++)
     {
         printf("Eleve N : %d\n",i+1);
         printf("Nom: %s\n",toto[i].nom);
         printf("Sexe: %c\n",toto[i].sexe);
         printf("Age : %d\n",toto[i].age);
         printf("----------------------\n");
     }
     
     
     
      system("PAUSE");	
      return 0;
    }
    ah oui, je vais remplacer le fflush (stdin) car j'ai lu que ce n'était pas bon pour vider le tampon dans la FAQ

    Oui, j'ai mis 5 pour effectuer un test sinon, par défaut, c'est 1.

    Par contre, quand tu me dis qu'il y a un risque de fuite de mémoire car ma valeur vaut NULL, que dois je faite pour ne pas rencontrer ce type de probleme.

    Je parle pour cette ligne de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ajouterEleve(ptab_eleve,&taille);


    Merci pour tout votre réponse

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 041
    Points
    33 041
    Billets dans le blog
    4
    Par défaut
    La fuite n'est pas dûe au simple NULL en entrée.
    Une fonction AjouterEleve, j'attends d'elle qu'elle ajoute un eleve à ma liste. La tienne se charge aussi de créer la liste (admettons, pourquoi pas), sans aucune vérification quant à l'existence ou pas préalable de la liste.
    Si ta liste existe déjà, y'a fuite.
    Apelle-la 2 fois, y'aura une fuite.

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    donc, si je comprends bien ton raisonnement, je dois faire une condition pour vérifier que mon pointeur vaut bien NULL avant d'appeler ma fonction ajouter si celui-ci n'est pas vide, je dois lever une exception

  13. #13
    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
    Repars sur des bases neuves et saines. Là tu perds ton temps à rafistoler un bout de code bricolé.
    Je t'ai donné une trame pour te permettre de faire un code correct. Si il te manque des explications, pose des questions.

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    Hello :-)

    je reviens à la charge avec ces pointeurs :-)

    Voila un premier jet qui contourne ceci : ELEVE ***ptab_eleve.

    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
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
     
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define VIDE fflush(stdin)
    /*
     * Tableau dynamique de pointeurs vers des élèves alloués dynamiquement
     */
    typedef struct eleve {
        char nom[40];
        char sexe ;
        int age ;
    } ELEVE ;
     
    ELEVE **ajouter (ELEVE **ptab, int *pn) ;
    void afficher (ELEVE **ptab, int n) ;
    int question(void) ;
    void encoder_eleve(ELEVE *) ;
    void afficher_eleve(ELEVE *) ;
     
    void libere_mem(ELEVE **ptab, int n) ;
     
    int main(int argc, char** argv) {
        ELEVE **ptab_eleve ;
        int nb_eleve ;
     
        ptab_eleve = NULL ;
        nb_eleve = 0 ;
     
        ptab_eleve = ajouter(ptab_eleve, &nb_eleve);
        afficher(ptab_eleve, nb_eleve);
     
        libere_mem(ptab_eleve,nb_eleve) ;
        return (EXIT_SUCCESS);
    }
    int question()
    {
       char reponse[254] ;
       strcpy(reponse,"O");
       printf ("\nVoulez_vous ajouter un eleve?") ;
       gets(reponse) ;
       if (!strcmp(reponse,"O") || !strcmp(reponse,"o"))
         return 1 ;
       else
         return 0 ;
     
    }
    void encoder_eleve(ELEVE *peleve){
       printf("\nNom:");
       gets(peleve->nom) ;
       printf("\nSexe:") ;
       scanf("%c",&(peleve->sexe));
       VIDE ;
       printf("\nAge:") ;
       scanf("%d",&(peleve->age));
       VIDE ;
    }
    ELEVE **ajouter(ELEVE **ptab, int *pn)
    {
       ELEVE *peleve ;
       int nb_eleve ;
     
       nb_eleve = *pn ;
     
       while (question())
       {
         ptab = (ELEVE **)realloc(ptab,(nb_eleve+1) * sizeof(ELEVE *)) ;
     
         peleve = (ELEVE *)malloc(sizeof(ELEVE)) ;
         encoder_eleve(peleve) ;
     
         *(ptab+nb_eleve) = peleve ;
     
         nb_eleve++ ;
     
       }
     
       *pn = nb_eleve ;
       return ptab ;
    }
     
    void afficher_eleve(ELEVE *pel)
    {
            printf("\nNom: %s", pel->nom);
            printf("\nSexe: %c", pel->sexe) ;
            printf("\nAge: %d", pel->age) ;
    }
     
    void afficher (ELEVE **ptab, int n) {
        int i ;
     
        printf("\n:%d: eleve(s)",n);
        for (i = 0; i < n; i++)
        {
            afficher_eleve(*(ptab+i)) ;
            printf("\n") ;
        }
     
    }
     
    void libere_mem(ELEVE **ptab, int n)
    {
        int i ;
     
        for (i = 0; i < n; i++)
        {
           free(*(ptab+i)) ;
        }
        free (ptab) ;
    }
    Ce code fonctionne

    Maintenant, j'essaie de refaire çà avec mes ***ptab_eleve :-)

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par diogene Voir le message
    Son prototype serait alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int ajouterEleve( ELEVE *** tab, int * n, ELEVE * eleve);
    Elle serait appelée de la façon suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ELEVE ** tableau = NULL;
    int ntab = 0;
    // création d'un ELEVE à l'adresse p : p = malloc(sizeof(ELEVE); + initialisation
    if (!ajouterEleve(&tableau,&ntab,p) printf("Erreur d'allocation");
    Ca ok, j'ai compris :-)

    Citation Envoyé par diogene Voir le message
    Le déroulement de la fonction int ajouterEleve(ELEVE *** tab,int *n, ELEVE * eleve) :
    -  Chercher si il y a une place libre dans le tableau débutant en *tab et ayant *n éléments :
        Chercher de i = 0 à i < *n si il y a un pointeur NULL dans le tableau.
    -  Si oui, mettre eleve à cette place, retourner 1
    
    Toujours ok, pas de soucis de compréhension.

    Citation Envoyé par diogene Voir le message
    -  Si non, agrandir le tableau de N (>0) cases (realloc()).
         -  En cas d'échec retourner 0
         -  En cas de succès 
              - mettre eleve en *n et mettre à NULL les pointeurs de *n+1 à *n+N-1
              - Copier la nouvelle valeur du nombre d'éléments *n+N dans *n
              - Copier la nouvelle adresse de départ du tableau dans *tab
              - retourner 1
    Là par contre, çà coince

    Je m'explique, le realloc, ca fonctionne (enfin je l’espère)... par contre pour l'affectation et l'affichage de données... ça plante :/

    Je montre mon ébauche de code. si on pouvait me dire ou ca coince car j'ai tout essayé et zéro. La compil fonctionne sans erreur mais l’exécution, il flanche :/

    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
     
    // Pointeur Structure.cpp*: définit le point d'entrée pour l'application console.
    //
     
    #include "stdafx.h"
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
     
     
    #define VIDE fflush(stdin)
     
     
    typedef struct personne
    {
    	char nom[40];
    	/*char sexe;
    	int age;*/
     
    } ELEVE;
     
    void ajouterEleve (ELEVE ***, int *);
    void afficherEleve (ELEVE **, int *);
     
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	ELEVE ** ptab_eleve=NULL,*p;
     
     
     
    	int taille=0,i=0;
     
    	ajouterEleve(&ptab_eleve,&taille);	
     
    	return 0;
    }
     
    void ajouterEleve (ELEVE *** ptab, int *nb)
    {
    	int i=0;
    	char reponse;
    	ELEVE *p;
     
    	p = (ELEVE*) malloc (sizeof (ELEVE));
    	if(p == NULL)
    		{
    			printf("Allocation impossible");
    		}
    	ptab =  (ELEVE ***) realloc (*(ptab),(*nb+1)*sizeof (ELEVE **));
    	if(ptab == NULL)
    		{
    			printf("Allocation impossible");
    		}
    	printf("\nVeuillez introduire le nom de l'eleve : ");
    	gets(p->nom);
    	VIDE;	
            *(*(ptab)+i) = p; // Il plante
     
    	//printf("\n Nom : %s\n", (**(ptab+i))->nom);
    }

  16. #16
    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
    1- on ne doit pas utiliser fflush() sur un flux d'entrée comme stdin. Le résultat est dépendant de l'implémentation (ne marche pas toujours). Voir la FAQ pour savoir comment vider le buffer d'entrée.

    2- ne pas utiliser gets() mais fgets() sur stdin

    3- Ce code ne correspond pas à la trame évoquée plus haut.
    - *nb n'est pas mis à jour
    - le nouveau pointeur ne doit pas être mis à l'index i (=0), mais en queue du nouveau tableau

    4- Plus grave :
    le realloc est incorrect :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ptab =  (ELEVE ***) realloc (*(ptab),(*nb+1)*sizeof (ELEVE **));
    ptab contient l'adresse du début du tableau de pointeurs. Il ne faut pas le modifier. Ce qu'il faut modifier, c'est le début du tableau et on devrait avoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *ptab= realloc(*ptab, (*nb+1)sizeof (ELEVE *))
    Il faut tenir compte de l'échec du realloc() et éviter dans ce cas une fuite mémoire par perte de l'adresse de l'ancien tableau. Le schéma doit être le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     p = realloc(*ptab,...)
     if(p == NULL)
     { // echec, on peut libérer la mémoire précédemment allouée par free(*ptab)
     }
     else // succès
     {
       *ptab = p;
       // suite du traitement

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    ah zut... et moi qui pensait etre dans le bon avec mon realloc :/

    enfin j'ai corrigé ce que tu m'a conseillé mais le *pat dans ton exemple ca correspond à quoi ?

    Par déduction, je suppose que c'est

    ELEVE **pat mais suis je dans le bon ? :-s

    car on en revient au problème d'affectation que j'ai depuis le debut

    Merci pour ton aide :-)

  18. #18
    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
    enfin j'ai corrigé ce que tu m'a conseillé mais le *pat dans ton exemple ca correspond à quoi ?
    A une erreur de frappe, il s'agit de ptab
    Je corrige mon post.

  19. #19
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Points : 59
    Points
    59
    Par défaut
    ouch... la je ne te suis plus du tout...


    si je comprends bien ce qu'il faut faire.

    Je fais un realloc pour ptab et p comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    *ptab= realloc(*ptab, (*nb+1)sizeof (ELEVE *));
     
    p = realloc(*ptab,...)
     if(p == NULL)
     { // echec, on peut libérer la mémoire précédemment allouée par free(*ptab)
     }
     else // succès
     {
       *ptab = p;
       // suite du traitement
    si j'essaie de comprendre, je dirais que la dernière ligne est une assignation mais peut être que je fais fausse route.. mais si c'est ainsi, ca ne va, j'ai une erreur d'assignation.

  20. #20
    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
    Faut pas tout mélanger :

    La ligne 2 du code que tu postes fait une reallocation qui entrainerait une fuite de mémoire en cas d'échec

    La suite du code (lignes 4 à 11) fait une reallocation qui peut tenir compte de l'échec

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Problème std::set avec une structure
    Par DeathMixer dans le forum C++
    Réponses: 4
    Dernier message: 03/10/2009, 01h05
  2. Problème sur un pointeur dans une structure
    Par steph_1 dans le forum Langage
    Réponses: 5
    Dernier message: 05/09/2007, 18h59
  3. Problème avec une structure
    Par titux dans le forum C
    Réponses: 5
    Dernier message: 22/07/2007, 16h26
  4. Problème avec une structure
    Par Pierre.g dans le forum C
    Réponses: 4
    Dernier message: 30/12/2006, 12h22
  5. Probléme avec une structure
    Par astragoth dans le forum C++
    Réponses: 3
    Dernier message: 25/04/2006, 20h31

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