[C - struct] return d'une structure
Charley
-
Charley -
Charley -
Bonjour,
Je recois lors du test de mon programme une erreur du type "segmentation fault" et je n'arrive absolument pas à voir d'où elle sort, toute aide sera appréciable.
Ce programme contient deux structures dont une inclue l’autre, l’idée est de réaliser un annuaire, on demande le nom, prénom et numéro de plusieurs personnes, que l’on stock dans la structure Personne. On prend ensuite 20 personnes de cette structure pour les mettre dans un carnet. Le carnet contient un second champ qui est le nombre de personnes présentes dans le carnet correspondant, autrement dit 20 si on avait bien 20 personnes dans la structure Personne.
Voici le programme:
Voilà, je l’ai édité sur Dev C++, sous Windows, le compilateur ne me retourne pas d’erreur, il m’exécute le programme jusqu'à la ligne de l’appel de la fonction ajout_ds_carnet() où une fenêtre apparaît avec le message : An access violation (Segmentation fault) raised in your program
Merci de votre attention, en espérant avoir une réponse rapidement, je vous remercie.
Je recois lors du test de mon programme une erreur du type "segmentation fault" et je n'arrive absolument pas à voir d'où elle sort, toute aide sera appréciable.
Ce programme contient deux structures dont une inclue l’autre, l’idée est de réaliser un annuaire, on demande le nom, prénom et numéro de plusieurs personnes, que l’on stock dans la structure Personne. On prend ensuite 20 personnes de cette structure pour les mettre dans un carnet. Le carnet contient un second champ qui est le nombre de personnes présentes dans le carnet correspondant, autrement dit 20 si on avait bien 20 personnes dans la structure Personne.
Voici le programme:
#include <stdio.h>
struct Personne {
char nom[32];
char prenom[32];
char numero[13];
};
struct Carnet {
struct Personne pc[20];
int nb_de_personnes;
};
struct Personne nouv_personne(char *nom,char *prenom,char *numero){
struct Personne p;
strcpy(p.nom,nom);
strcpy(p.prenom,prenom);
strcpy(p.numero,numero);
return (p);
}
struct Carnet ajout_ds_carnet(int i, char *nom, char *prenom, char *numero){
struct Carnet c;
strcpy(c.pc[i].nom,nom);
strcpy(c.pc[i].prenom,prenom);
strcpy(c.pc[i].numero,numero);
c.nb_de_personnes++;
return (c);
}
main(){
int i,j=0;
for (i=0; i<5; i++){ //On demande d’entrer seulement 5 personnes
if (i==20) { i=0; j++; }
struct Personne p[i];
char nom[32],prenom[32],numero[13];
printf("Entrez le nom du %d:",i); scanf("%s",nom);
printf("Entrez le prenom du %d:",i); scanf("%s",prenom);
printf("Entrez le numero du %d:",i); scanf("%s",numero);
p[i] = (*nouv_personne)(nom, prenom, numero);
printf("(%s, %s, %s) a été ajouté à la structure Personne\n",p[i].nom,p[i].prenom,p[i].numero);
struct Carnet c[j]; /* Le problème se situe à partir de cette ligne */
c[j] = (*ajout_ds_carnet)(i, p[i].nom, p[i].prenom, p[i].numero);
printf("\nCarnet n°%d, ligne n°%d contient: ((%s,%s,%s),%d)",j,i+1,c[j].pc[i].nom,c[j].pc[i].prenom,c[j].pc[i].numero,c[j].nb_de_personnes);
}
Voilà, je l’ai édité sur Dev C++, sous Windows, le compilateur ne me retourne pas d’erreur, il m’exécute le programme jusqu'à la ligne de l’appel de la fonction ajout_ds_carnet() où une fenêtre apparaît avec le message : An access violation (Segmentation fault) raised in your program
Merci de votre attention, en espérant avoir une réponse rapidement, je vous remercie.
A voir également:
- [C - struct] return d'une structure
- Logiciel calcul structure bois gratuit - Télécharger - Architecture & Déco
- Structure d'un rapport de stage - Guide
- Zuma return - Télécharger - Jeux vidéo
- Structure url - Guide
- Return to castle wolfenstein patch fr ✓ - Forum Jeux vidéo
2 réponses
Quand tu alloue un élément à une structure, tableau, variable, etc.. i lfaut allouer également l'espace nécessaire. Pour les variables et autres trucs simple c'est fait tout seul, mais pour ce qui est des structures, tu dois impérativement allouer l'espace mémoire nécéssaire au stockage de tes données.
Ainsi, lorsque tu fais dans ta fonction d'ajout de personne :
Tu n'alloue pas de mémoire à ton élément 'p', si bien que le prog ne peut rien copier dans ton élément p.
Idem pour ce qui est de l'ajout dans ton annuaire, sauf que là il te fais une erreur car tu accede directement à un espace non alloué comme suit :
lorsque tu fais 'c.pc[i].nom', c.pc[i] est sensé etre alloué, ce qui n'est pas ton cas.
Donc il te faut allouer l'espace mémoire avant d'utiliser ta structure, de meme pour les tableaux, ainsi ton main devient :
La fonction malloc permet d'allouer une taille fixe à un moment donné, et la fonction calloc (si mes souvenir sont bons, je n'ai pas vérifié) permet d'allouer sur le moment un espace, donc utile ici pour allouer une case de pllus à chaque passage.
PS : il te faut aussi modifier tes fonctions en allouant la mémoire nécessaire à chaque structure que tu créé au départ, mais je te laisse le soin de le faire pour voir si tu as compris ou pas ;)
--@ droate, iclic, iclic
et ya pas de bôg môsieu ! ~
Ainsi, lorsque tu fais dans ta fonction d'ajout de personne :
struct Personne p;
strcpy(p.nom,nom);
strcpy(p.prenom,prenom);
strcpy(p.numero,numero);
return (p);
Tu n'alloue pas de mémoire à ton élément 'p', si bien que le prog ne peut rien copier dans ton élément p.
Idem pour ce qui est de l'ajout dans ton annuaire, sauf que là il te fais une erreur car tu accede directement à un espace non alloué comme suit :
strcpy(c.pc[i].nom,nom);
lorsque tu fais 'c.pc[i].nom', c.pc[i] est sensé etre alloué, ce qui n'est pas ton cas.
Donc il te faut allouer l'espace mémoire avant d'utiliser ta structure, de meme pour les tableaux, ainsi ton main devient :
main(){
int i,j=0;
// --- ICI TU ALLOUE TON TABLEAU POUR 5 PERSONNES
struct Personne *p = malloc ( 5 * sizeof( Personne ) );
struct Carnet *c = null;
for (i=0; i<5; i++){ //On demande d’entrer seulement 5 personnes
if (i==20) { i=0; j++; }
// --- Comme ca ici tu peux utiliser correctement :
struct Personne p[i];
char nom[32],prenom[32],numero[13];
printf("Entrez le nom du %d:",i); scanf("%s",nom);
printf("Entrez le prenom du %d:",i); scanf("%s",prenom);
printf("Entrez le numero du %d:",i); scanf("%s",numero);
p[i] = (*nouv_personne)(nom, prenom, numero);
printf("(%s, %s, %s) a été ajouté à la structure Personne\n",p[i].nom,p[i].prenom,p[i].numero);
c = calloc ( sizeof( Carnet ));
c[j] = (*ajout_ds_carnet)(i, p[i].nom, p[i].prenom, p[i].numero);
printf("\nCarnet n°%d, ligne n°%d contient: ((%s,%s,%s),%d)",j,i+1,c[j].pc[i].nom,c[j].pc[i].prenom,c[j].pc[i].numero,c[j].nb_de_personnes);
}
La fonction malloc permet d'allouer une taille fixe à un moment donné, et la fonction calloc (si mes souvenir sont bons, je n'ai pas vérifié) permet d'allouer sur le moment un espace, donc utile ici pour allouer une case de pllus à chaque passage.
PS : il te faut aussi modifier tes fonctions en allouant la mémoire nécessaire à chaque structure que tu créé au départ, mais je te laisse le soin de le faire pour voir si tu as compris ou pas ;)
--@ droate, iclic, iclic
et ya pas de bôg môsieu ! ~
Je dois dire qu’elle me fait réfléchir, je n’ai jamais utilisé ces fonctions, malloc, calloc, et je suis un peu perdu, j’ai donc essayé de m’y mettre en cherchant à droite à gauche mais j’ai quelques difficultés à mettre en pratique.
Comme tu disais, c.p[i] doit être alloué, j’ai donc tenté un semblant d’allocation sans succès, et je ne m’en sors pas vraiment, voici ce que j’ai fait :
Mais le compilateur me sort une erreur de syntaxe « syntaxe error before ‘.’ token » je ne comprend pas trop…
Pour en revenir à ce que tu me proposait :
struct Personne *p = malloc(5*sizeof(struct Personne)); struct Carnet *c = 0;Si j’ai bien compris la première ligne sert à réserver de l’espace mémoire pour 5 structures Personne, donc 5*(nom, prenom, numero), mais pour la seconde ligne j’ai du mal à voir pourquoi est-ce qu’on la met à 0, on devrait bien réserver de la place pour les champs du carnet aussi non ?
Quant à l’utilisation de calloc un peu plus loin dans le main :
Je ne vois pas trop non plus pourquoi on l’alloue ici avec calloc et non malloc, et pourquoi pas en début de programme ?
Je débute complètement avec ces fonctions, désolé si je parais un peu à côté de la plaque, j’essaye de comprendre et j’apprécierai toutes corrections éventuelles. Merci
struct Personne { char nom[32]; char prenom[32]; char numero[13]; }; struct Carnet { struct Personne **pc; int nb_de_personnes; };Ainsi tu remarque que tu n'as plus la taille qui est passée à ton tableau de Personne dans ta structure Carnet. Normal, car pc va être en fait un pointeur de pointeur qui pointera sur des structures Personnes. En gros c'est la représentation d'un tableau sous forme de pointeur.
Pour l'initialiser tu fais comme suit (et donc pour la création d'un seul carnet) :
Carnet *c = null; // pointeur sur structure Carnet. Personne *p = null; int nombrePersonne = 10; // Nb personne a mettre dans carnet // allocation de la mémoire pour le carnet : c = malloc ( sizeof ( struct Carnet )); // --- Rempli le nombre de personne pour le carnet c.nb_de_personnes = nombrePersonne; // --- Alloue l'espace mémoire pour le tableau de personne : c.pc = (**Personne) malloc ( c.nb_de_personnes * sizeof ( *Personne)); // --- Attention, ici tu n'as alloué que l'espace pour des pointeurs sur // ---structure !! Ce qui va te permettre de faire : c.pc[i] dans une // ---boucle pour remplir une à une tes personnes dans le carnet // --- On rempli ensuite les personnes pour chaque case du carnet : for ( int i = 0; i < nombrePersonne; i++){ // --- création d'un personne (allocation) p = ( *Personne ) malloc (sizeof ( Personne )); // --- création d'une personne (informations) p.nom = "..."; p.prenom = "..."; p.numero = "..."; // --- Ajout de la personne dans le carnet : c.pc[i] = p; }Voilà en gros comment on fais. Le probleme c'est que c'est certainement faux et que ca ne compile pas. Je n'ai pas d'environnement C sous la main et ca fais 4 ans que je n'ai pas touché à une ligne de code en C donc...
Il faudrait que tu potasse les pointeurs, structures, etc... et que tu regarde de nouveau avec quelqun dont les souvenirs sont plus récents :p
Bon courage pour la suite.
Exemple : Je rentre un nom, prenom, numero pour le premier bouclage de i(=0); ils sont insérés dans Personne et dans Carnet aux valeurs p[0].nom, (*c[0].pc[0]).nom respectivement ; etc pour prenom et numero. L’affichage est correct et j’ai bien mes nom, prenom et numero dans ces valeurs.
Au prochain bouclage i passe à 1, p[1].nom, (*c[0].p[1]).nom sont bien affectés, mais lorsque je veux voir la valeur précédente dans le carnet : (*c[0].p[0]).nom elle ne s’affiche plus !
C’est sûrement dû à un changement d’adresse, enfin j’ai du mal à voir où est le problème exactement… peut être que quelqu’un peut m’éclairer ? :)
Le programme est :
struct Personne { char nom[32]; char prenom[32]; char numero[13]; }; struct Carnet { struct Personne **pc; int nb_de_personnes; }; struct Personne nouv_personne(char *nom,char *prenom,char *numero){ struct Personne *p; p = malloc(sizeof(struct Personne)); strcpy((*p).nom,nom); strcpy((*p).prenom,prenom); strcpy((*p).numero,numero); return (*p); } struct Carnet ajout_ds_carnet(int i, struct Personne *p2, int nb_prec){ struct Carnet *c; c = malloc (sizeof ( struct Carnet )); (*c).pc[i] = &p2[i]; (*c).nb_de_personnes = nb_prec; (*c).nb_de_personnes++; printf("\n\n(%s,%s,%s) a été ajouté au carnet",(*(*c).pc[i]).nom,(*(*c).pc[i]).prenom,(*(*c).pc[i]).numero); printf("\nIl contient %d personnes",(*c).nb_de_personnes); return (*c); } main(){ int i,j=0; struct Personne *p = NULL; struct Carnet *c = NULL; int nombrePersonne = 5; c = malloc (sizeof ( struct Carnet )); (*c).pc = malloc (nombrePersonne * sizeof ( struct Personne)); p = malloc (nombrePersonne * sizeof(struct Personne)); (*c).nb_de_personnes = 0; for (i=0; i<nombrePersonne; i++){ if (i==15) { i=0; j++; } printf("\n =-=-=-=-=-=- Personne: %d -=-=-=-=-=-=-=\n\n",i); char nom[32],prenom[32],numero[13]; printf("Entrez le nom du %d:",i); scanf("%s",nom); printf("Entrez le prenom du %d:",i); scanf("%s",prenom); printf("Entrez le numero du %d:",i); scanf("%s",numero); p[i] = (*nouv_personne)(nom, prenom, numero); printf("(%s, %s, %s) a été ajouté à la structure Personne\n",p[i].nom,p[i].prenom,p[i].numero); c[j] = (*ajout_ds_carnet)(i,p,c[j].nb_de_personnes); printf("\np[0].nom: %s - c[0].pc[0].nom: %s\n",p[0].nom,(*c[0].pc[0]).nom); printf("\nc[0].nb_de_personnes: %d\n",c[0].nb_de_personnes); //OK printf("\nCarnet n°%d, ligne n°%d contient: ((%s,%s,%s),%d)\n\n",j+1,i+1,(*c[j].pc[i]).nom,(*c[j].pc[i]).prenom,(*c[j].pc[i]).numero,c[j].nb_de_personnes); } }