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 de structure


Sujet :

C

Vue hybride

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

    Informations forums :
    Inscription : Mai 2011
    Messages : 17
    Par défaut Allocation dynamique d'un tableau de structure
    Bonjour,
    Je dois programmer un jeu de Yathzee pour un projet de fac en C, et j'ai un petit problème concernant une déclaration dynamique d'un tableau de structure. Je m'explique :
    J'ai deux structure (dans deux fichier .C différent)

    La première :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct FeuilleScore {  
    int partieSuperieure [9];  
    int partieInferieure [7];  
    int scoreFinal;  
    };
    (j'ai mis dans un fichier .h correspondant : struct feuilleScore

    et la deuxieme :
    (j'ai mis en début de fichier #include "ProjetB.h" (c'est le .h du fichier .c où j'ai déclaré ma structure feuilleScore))

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct Joueur {  
    char* nom;  
    int nblancerRestants;  
    int Des [5]; //les dés du joueur (5 dés)  
    struct FeuilleScore;  
    };
    Le but est de créer le bon nombre de structures Joueur (une pour chaque joueurs de la partie).

    j'ai donc fait cette petite fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     struct Joueur* nombreJoueurs(void){  
     int nombreJoueurs;  
     printf("Combien de joueurs vont participer a la partie ? (1/2/3/...)");  
     scanf("%d",&nombreJoueurs);  
        struct Joueur* tab;  
        tab = malloc(sizeof(tab) * nombreJoueurs);  
        return tab;  
    }
    jusque là pas de problèmes.
    Puis j'ai fais une fonction qui permet d'associer a chaque structures Joueurs le nom du joueur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void nomJoueurs (struct Joueur * tab) {  
        int i = 0;  
        for(i;i<sizeof(tab);i++){  
            printf("Nom du joueur %d ? ",i+1);  
            scanf("%s",tab[i].nom);  
        }  
    }
    sauf qu'a partir de là ... ça ne marche plus du tout, peut importe le nombre de joueurs , mon nomJoueurs me propose toujours le nom de deux joueurs a mètre, et ensuite windows me dit que mon programme a cessé de fonctionner.

    Je pense donc que le problème vient de mon allocation dynamique de ma structure. Dois-je faire la même chose pour la structure FeuilleScore qui est dans la structure Joueur ?

    Merci d'avance

  2. #2
    Invité
    Invité(e)
    Par défaut
    Il te faut un tableau à deux dimensions, le programme quitte car il fait une erreur de segmentation fault en essayant d'accéder à une zone qui ne lui a pas été allouée

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Salut

    donne la taille du pointeur et non la taille de l'objet pointé. Du coup, ça ne peut pas marcher correctement.

    Je trouve le nom de la fonction nombreJoueurs assez moyen, vu que sa principale fonction est d'allouer de la mémoire. creerJoueurs ou quelque chose du genre conviendrait peut-être mieux.

    Tu peux créer un tableau dynamique possédant un nombre d'éléments correspondant au nombre de joueurs, chacun de ces éléments étant un pointeur sur une structure Joueur. Et via une boucle, il suffit ensuite d'allouer de la mémoire pour chacun de ces pointeurs, d'une taille de la structure.

    La fonction retourne la mémoire allouée, mais elle doit aussi faire connaitre à la fonction appelante le nombre de joueurs saisi (on peut le faire en passant un pointeur sur "int" en argument, pointant sur un objet "int" de la fonction appelante, où il suffira de modifier la valeur pointée).

    Tu peux donc par exemple créer un prototype de ce genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct Joueur ** creerJoueurs(int * nombre_joueurs)
    Et modifier aussi le prototype de la fonction nomJoueurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int nomJoueurs(struct Joueur ** joueurs , int nombre_joueurs)
    La fonction serait appelée comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct Joueur ** joueurs;
    int nombre_joueurs;
     
    joueurs = creerJoueurs(&nombre_joueurs);
    if (joueurs == NULL)
    {
     ... erreur ...
    } else
    {
    ...
    }
    ce qui permettrait ensuite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ...
    if (nomJoueurs(joueurs , nombre_joueurs) == 0)
    {
     ... erreur ...
    } else
    {
    ...
    }
    ...

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 17
    Par défaut
    voila mes deux fonctions :

    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
    struct Joueur** creerJoueurs (int * nombre_joueurs){
        int i = 0;
    	int nombreJoueurs;
    	printf("Combien de joueurs vont participer a la partie ? (1/2/3/...) ");
    	scanf("%d",&nombreJoueurs);
    	*nombre_joueurs = nombreJoueurs;
        struct Joueur** tab;
        tab[nombreJoueurs];
        for(i;i<nombreJoueurs;i++){
            tab[i] =  malloc(sizeof(struct Joueur));
        }
        return tab;
    }
     
    void nomJoueurs (struct Joueur** tab,int nombre_joueurs) {
        int i = 0;
        printf("%d",nombre_joueurs);
        for(i;i<nombre_joueurs;i++){
            printf("Nom du joueur %d ? ",i+1);
            scanf("%s",(*tab[i]).nom);
        }
    }
    cependant , lorsque j'exécute mes fonction par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int main (void) {
        int taille;
        nomJoueurs(creerJoueurs(&taille),taille);
    }
    je ne peu pas rentrer de nom pour les joueurs :/ qu'est-ce que j'ai loupé ?

  5. #5
    Invité
    Invité(e)
    Par défaut
    Tu dois malloquer ton tableau avant de l'utiliser !

    Cette ligne ne fait rien à part faire planter ton programme : tab[nombreJoueurs];

    Il y a de nombreux sujets sur le malloc de tableaux à deux dimensions, fais une petite recherche.

  6. #6
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct Joueur** creerJoueurs (int * nombre_joueurs)
    {
     ....
        struct Joueur** tab;
        tab[nombreJoueurs];
        for(i;i<nombreJoueurs;i++){
            tab[i] =  malloc(sizeof(struct Joueur));
        }
        return tab;
    }
    tab[nombreJoueurs] ne fait rien.
    tab[i] =.... est faux, puisqu'on n'a pas alloué de mémoire pour tab[i]

    Il faut également tester la réussite des allocations.
    Par exemple :
    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
    struct Joueur** creerJoueurs (int * nombre_joueurs)
    {
        int i ;
        int nombreJoueurs = 0;
        *nombre_joueurs  = 0;
         do
         {
              printf("Combien de joueurs vont participer a la partie ? (1/2/3/...)\n");
              scanf("%d",&nombreJoueurs);
         }while(nombreJoueurs <=0)
     
       // allocation de la table des pointeurs
        struct Joueur** tab = malloc(nombreJoueurs*sizeof *tab);
        if(tab != NULL)
        {
            // allocation des joueurs
            for(i=0;i<nombreJoueurs;i++)
            {
                 tab[i] =  malloc(sizeof(struct Joueur));
                 if(tab[i] == NULL) break;
            }
            if(i<nombreJoueurs) // erreur d'allocation dans tab[i]
            {
                     // récupérer la mémoire allouée pour les tab[k] k=0..i-1
                     // récupérer la mémoire allouée pour tab
                     // mettre tab à NULL
            }
        }
        if(tab != NULL)  *nombre_joueurs  = nombreJoueurs ;
        return tab;
    }
    Maintenant, pourquoi faire un tableau de pointeurs sur des structures joueurs plutôt qu'un tableau de structure joueurs ? Ce serait plus simple.

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Citation Envoyé par TheChicken Voir le message
    voila mes deux fonctions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    struct Joueur** creerJoueurs (int * nombre_joueurs){
        int i = 0;
    	int nombreJoueurs;
    	printf("Combien de joueurs vont participer a la partie ? (1/2/3/...) ");
    	scanf("%d",&nombreJoueurs);
    	*nombre_joueurs = nombreJoueurs;
        struct Joueur** tab;
        tab[nombreJoueurs];
        for(i;i<nombreJoueurs;i++){
            tab[i] =  malloc(sizeof(struct Joueur));
        }
        return tab;
    }
    Quelques remarques :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	int nombreJoueurs;
    	printf("Combien de joueurs vont participer a la partie ? (1/2/3/...) ");
    	scanf("%d",&nombreJoueurs);
    	*nombre_joueurs = nombreJoueurs;
    On peut écrire directement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	printf("Combien de joueurs vont participer a la partie ? (1/2/3/...) ");
    	scanf("%d",nombre_joueurs);
    -------

    Ceci ne fait rien. En plus, ça déborde.
    Il faut allouer de la mémoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct Joueur** tab;
    tab = malloc( sizeof *tab * *nombre_joueurs);
    -------

    Il n'y a nulle part aucun contrôle sur le retour des malloc. C'est "dangereux" car si la fonction échoue ça fait planter le programme.

    -------

    Le programme doit toujours libérer lui-même la mémoire dynamique qu'il a allouée (une fois qu'il n'en a plus besoin)

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Maintenant, pourquoi faire un tableau de pointeurs sur des structures joueurs plutôt qu'un tableau de structure joueurs ? Ce serait plus simple.
    J'avoue que j'ai un peu compliqué l'affaire avec cette idée. C'était pas très utile pour ce genre de programme.
    Au pire, à ce stade (y a pas bcp de code encore), on peut revenir à l'autre solution, il y a peu de choses à modifier.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 17
    Par défaut
    J'ai complété le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if(i<nombreJoueurs){ // erreur d'allocation dans tab[i]
                for(k=0;k<nombreJoueurs;k++){
                    free(tab[k]);// récupérer la mémoire allouée pour les tab[k] k=0..i-1
                }
                free(tab);// récupérer la mémoire allouée pour tab
                tab = NULL;// mettre tab à NULL
            }
    mais ma fonction nomJoueurs ne fonctionne pas (je passe une fois dans ma boucle for (puisque "Nom du joueur 1 ? " apparait ), mais après mon programme bug)

    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
    void nomJoueurs (struct Joueur** tab,int nombre_joueurs) {
        int i = 0;
        char* temporaire;
        for(i;i<nombre_joueurs;i++){
            printf("Nom du joueur %d ? ",i+1);
            scanf("%s",temporaire);
            (*tab[i]).nom = malloc(sizeof(char)*strlen(temporaire)+1);
            strcpy(temporaire,(*tab[i]).nom );
        }
    }
    int main (void) {
        int taille;
        nomJoueurs(creerJoueurs(&taille),taille);
        return 0;
    }

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 17/01/2012, 17h01
  2. Allocation dynamique d'un tableau de structures
    Par ryadh.naouar dans le forum C
    Réponses: 5
    Dernier message: 24/04/2008, 12h49
  3. Réponses: 67
    Dernier message: 13/02/2007, 18h08
  4. Réponses: 13
    Dernier message: 01/10/2006, 00h25
  5. [PRO*C] Allocation dynamique d'un tableau de VARCHAR
    Par NéalZheimer dans le forum Interfaces de programmation
    Réponses: 5
    Dernier message: 07/07/2006, 13h02

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