C++ problème pointeur

Résolu/Fermé
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009 - 5 janv. 2009 à 11:49
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009 - 7 janv. 2009 à 16:06
Bonjour,

Voilà j'ai un programme avec des listes chaînées sur un arbre généalogique simplifié voici la structure d'un individu :

struct Feuille
{
string Nom;
string Prenom;
string Date_naiss;
Feuille * FrereSoeurPrecedent;
Feuille * FrereSoeurSuivant;
Feuille * TeteAscendent;
Feuille * TeteDescendance;
};

J'ai écrit une fonction rechercher qui permet de trouver un prénom dans l'arbre existant voici le code :

Feuille* rechercher(string prenom,Feuille * p)
{
cout << p->Prenom << "av boucle" << endl;
getch();
while(p!=NULL && p->Prenom!=prenom){
cout << p->Prenom << "dans boucle" << endl;
getch();
if(p->TeteDescendance!=NULL){
rechercher(prenom,p->TeteDescendance);
}
p=p->FrereSoeurSuivant;
}
cout << p->Prenom << "ap boucle" << endl;
getch();
if(p->Prenom==prenom){
return p;
}
else{
return NULL;
}
};

en lançant la fonction j'obtiens le message suivant:
0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0x00000038.

14 réponses

MRAD Messages postés 86 Date d'inscription mardi 21 octobre 2008 Statut Membre Dernière intervention 17 avril 2009 4
5 janv. 2009 à 12:58
Bonjour,
Le code semble bien ecrit, et ce n'est question d'allocation memoire ici, p est un parametre parvenue du main donc il sera declarer dans le main, est ce que je pe avoir le code de ton main ?
1
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
7 janv. 2009 à 12:14
Oui, logique, j'ai juste corrigé ce que tu avais écrit. Il faut aussi descendre dans les raternités
Feuille* rechercher(string prenom,Feuille * p)
{
   cout << p->Prenom << "av boucle" << endl;
   getch();
   Feuille*tmp=p,*tmp1;
   while(p!=NULL ){
      cout << p->Prenom << "dans boucle" << endl;
      getch();
      if(p->Prenom==prenom) return p;
      if(tmp1=rechercher(prenom,p->TeteDescendance)!=0)return tmp1;
      p=p->FrereSoeurSuivant;
   }
/*   p=tmp;
   if(p->TeteDescendance!=NULL){
       return rechercher(prenom,p->TeteDescendance);
   }
   else*/ return NULL;
}; 
Je pense que là tu devrais parcourir tout l'arbre.
1
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009
7 janv. 2009 à 16:06
J'ai enlevé les lignes inutiles et ajouté un petit commentaire et des parenthèses dans le test de relance :

Feuille* rechercher(string prenom,Feuille * p)
{
   Feuille*tmp;
   while(p!=NULL ){
      if(p->Prenom==prenom) return p;
	  //Relance la recherche sur les descendants de p renvoi p si p->prenom==prenom
      if((tmp=rechercher(prenom,p->TeteDescendance))!=NULL)return tmp;
      p=p->FrereSoeurSuivant;
   }
   return NULL;
};


Maintenant cela fonctionne pour tout l'arbre! Merci beaucoup d'avoir passé du temps sur mon problème!
0
Utilisateur anonyme
5 janv. 2009 à 12:37
c est tou bete, il n y a pas d allocation mémoire ...

il te faut un

p = new Feuille(p);

en debut de fonction
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
5 janv. 2009 à 12:54
Salut.
Là je ne voi pas d'où peut provenir l'erreur.
As tu bien fermé tout tes arbres avec un NULL ?
Attention aussi aux arbres à double sens (precedent suivant) le traitement est un peu plus compliqué est peu causer des erreurs.
Dans ces cas là, il faut voir l'historique complet de l'exécution de ton programme et savoir exactement où il plante.

Si, petite erreur d'algo : après avoir chercher dans les descandants, tu met p à frere_soeur_suivant, même si la recherche s'est bien dérouler.
Par contre, si la recherche s'est mal dérouler, p devient NULL et tu essai d'accéder à FrereSoeurSuivant, ce qui peux provoqué une erreur. Il faut voir la taille d'un string, mais ça pourrait expliqué le 0x00038
si p vaut zéro, alors &(p->FrereSoeurSuivant) vaut : sizeof(prenom)+sizeof(nom)+sizeof(Date_nais)+sizeof(Feuille*)
38 en hexa donne 56 en décimal, si le pointeur est sur 8 octet (64 bit), il reste donc 48/3=16 octet pour chaque string
0
Utilisateur anonyme
5 janv. 2009 à 12:56
je sais pas si t avais lu, mais j avais répondu ... j ai deja eu ce probleme et c était ca
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009
5 janv. 2009 à 14:25
Merci pour vos réponses,

Le Main étant assez conséquent je n'écrirais que la partie concerné.

p est déclaré de cette manière dans main :

Feuille * p=NULL;


la fonction rechercher est lancé de cette manière

recherche("Firmin",p=tete);

tete est la tête de la liste chaînée.
"Firmin" est saisie par l'utilisateur.

L'arbre commence par "Leon" qui n'a pas de frère ou soeur et qui a "Firmin" comme 1ér enfant

Quand je lance la fonction ecrit au dessus la trace est la suivante :

Leon av boucle
Leon dans boucle
Firmin av boucle
Firmin ap boucle
PLANTAGE DU PROGRAMME :
0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0x00000038.

Quand je lance la fonction avec "Leon" comme prénom elle fonctionne car elle ne passe pas tant que.

J'ai fait un test en modifiant le statut de Firmin je le fait devenir le frere de Leon plutôt que son fils dans ce cas là la fonction marche aussi.

Le problème est à partir du moment que je rappelle la fonction rechercher le programme plantera.

Merci de votre aide.
0
Utilisateur anonyme
5 janv. 2009 à 14:26
tu n as donc pas alloué de mémoire à p dans le main

aprés Feuille * p=NULL; écrit

p = new Feuille(p);

ca devrait peut etre marcher
0
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009
5 janv. 2009 à 14:42
non ça ne peut pas marcher il faut allouer de la mémoire seulement quand on veut insérér des nouvelles données.

Or la je veut juste me positionner sur l'adresse mémoire qui contient p->prenom == "Firmin".

Je lance la fonction avec comme argument recherche("Firmin",p=tete) .

p vaut tete donc pourquoi je mettrais ensuite dans la fonction p = new Feuillle;
0
Utilisateur anonyme
5 janv. 2009 à 14:46
oui mais dans ce que tu as mis pour le main, p est null donc il y a recherche dans le vide, ou alors tu a rentré une données dans p mais je ne vois pas non plus d allocation pour celui ci . sinon, essaye sans mettre p en pointeur de structure dans le main et de le passer en paramettre avec un &
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298 > Utilisateur anonyme
5 janv. 2009 à 15:00
laisse tombé, le problème ne viens pas de là, sinon le programme planterai des la première ligne, alors que là on voi clairement que le premier affichage est cohérent.
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
5 janv. 2009 à 14:58
Comme je t'ai dit, ça viens de l'algo.
Attention à la subtilité de ton code !
tu fait un appel récurent à recherche ! donc en partant de leon, il descend et relance la fonction recherche("firmin",Leon->TeteDescendance); Là il trouve car Firmin est directement un fils de leon, donc il marque "Firmin ap boucle" et sort de la seconde fonction rechercher pour revenir dans la première, la tu met p à Firmin->freresuivant et tu demande son prénom. Si firmin n'as pas de frere c'est normal que ça plante !
Feuille* rechercher(string prenom,Feuille * p)// p pointe une premire fois sur Leon puis sur Firmin
{
   cout << p->Prenom << "av boucle" << endl;
   getch();
   while(p!=NULL && p->Prenom!=prenom){
      cout << p->Prenom << "dans boucle" << endl;
      getch();
      if(p->TeteDescendance!=NULL){
          rechercher(prenom,p->TeteDescendance);// là tu passe Firmin à rechercher()
      }
      p=p->FrereSoeurSuivant;//  si p vaut Leon, p pointe maintenant vers son frère, c'est là qu'est l'erreur
   }
   cout << p->Prenom << "ap boucle" << endl;
   getch();
   if(p->Prenom==prenom){
      return p;
   }
   else{
      return NULL;
   }
}; 

ta logique est mauvaise, à retravailler.
0
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009
5 janv. 2009 à 15:03
Feuille * p=NULL;
p est un pointeur sur la structure Feuille initialisé à NULL

quand je lance la fonction recherche je fais
p=tete;
tete est le premier pointeur sur Feuille de ma liste chaînée

J'insiste on n'alloue pas plusieurs fois pour les même informations donc vu que p=tete je n'ai pas a mettre
p = new Feuille;
0
Utilisateur anonyme
5 janv. 2009 à 15:06
quand tu fais p=tete, ca n allou rien, au contraire, si ca n est pas alloué, il y aura un probleme (sans message d erreur lors de la compilation). mais aprés, tu fais ce que tu veux :D
0
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009
5 janv. 2009 à 15:10
Je voudrais que quand la fonction trouve Firmin elle fait return p où p=Firmin
Et que une fois que j'ai fait un return toute les fonctions rechercher lancé avant soit s'arrete soit renvoi p=Firmin

C'est possible, si oui comment faire?
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
5 janv. 2009 à 15:39
Pour ça, il faut tester le retour de ta fonction rechercher. Deux solutions, une facile mais n'explorant pas tout :
Feuille* rechercher(string prenom,Feuille * p)
{
   cout << p->Prenom << "av boucle" << endl;
   getch();
   while(p!=NULL && p->Prenom!=prenom){
      cout << p->Prenom << "dans boucle" << endl;
      getch();
      if(p->TeteDescendance!=NULL){
          return rechercher(prenom,p->TeteDescendance);
      }
      p=p->FrereSoeurSuivant;
   }
   cout << p->Prenom << "ap boucle" << endl;
   getch();
   if(p->Prenom==prenom){
      return p;
   }
   else{
      return NULL;
   }
}; 
Une plus propre (enfin j'espère)
Feuille* rechercher(string prenom,Feuille * p)
{
   cout << p->Prenom << "av boucle" << endl;
   getch();
   while(p!=NULL ){
      cout << p->Prenom << "dans boucle" << endl;
      getch();
      if(p->Prenom==prenom) return p;
      p=p->FrereSoeurSuivant;
   }
   if(p->TeteDescendance!=NULL){
       return rechercher(prenom,p->TeteDescendance);
   }
   else return NULL;
}; 
tu cherche d'abord dans les freres et soeur, et si tu n'y trouve rien, tu cherches dans les descendants. Et tu retourne NULL si il n'y en a pas.
0
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009
5 janv. 2009 à 16:55
Merci pour tes solutions, malheureusement elles ne fonctionnent pas pour tout l'arbre.

Je voulais me servir de la récursivité pour diminuer et clarifier le code mais j'ai l'impression que ce sera pas pour tout de suite

Voici la fonction Rechercher sans récursivité que j'ai écrite et qui fonctionne pour tous les cas, c'est une usine à gaz mais sa marche si tu trouve plus simple merci de me prévenir

Feuille* rechercher(string prenom,Feuille * p)
{
Feuille * tete_liste = NULL;
Feuille * suite_liste = NULL;
Feuille * liste_descendant=NULL;
//la boucle cherche la personne avec le prenom donné
while(p->Prenom!=prenom && p!=NULL){
//gére le cas où un des enfants de la liste du descendant actuel à des descendants
if (p->FrereSoeurSuivant!=NULL && p->TeteDescendance!=NULL){
if(tete_liste==NULL){
tete_liste = p->TeteDescendance;
liste_descendant = tete_liste;
}
else{
if (suite_liste==NULL){
suite_liste=p->TeteDescendance;
tete_liste->TeteDescendance=suite_liste;
}
else{
suite_liste->TeteDescendance=p->TeteDescendance;
suite_liste=suite_liste->TeteDescendance;
}
}
}
//Si p a un frere on passe à son frere
if(p->FrereSoeurSuivant!=NULL){
p = p->FrereSoeurSuivant;
}
//Si p n'a pas de frere
else{
//Si p a un descendant
if(p->TeteDescendance!=NULL){
p = p->TeteDescendance;
}
//Si p n'a pas de descendant
else{
//Si il y existe un descendant pour un frere ou descendant precedent
if(tete_liste!=NULL){
p = tete_liste;
tete_liste = tete_liste->TeteDescendance;
}
else{
p = NULL;
}
}
}
}
if(p->Prenom==prenom){
return p;
}
else{
return NULL;
}
};

PS:pour Nagashiwa il n'y a pas d'allocation de mémoire dans ma fonction et elle marche parfaitement.
0
Utilisateur anonyme
5 janv. 2009 à 16:57
xd rageu :p
okok, j admet, mais c est que j avais eu un probleme similaire il y a 3 semaine et il me semblait l avoir résolu avec ca mais je dois me trmper ^^
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
5 janv. 2009 à 18:01
Normal, ereur de ma part. essai
Feuille* rechercher(string prenom,Feuille * p)
{
   cout << p->Prenom << "av boucle" << endl;
   getch();
   Feuille*tmp=p;
   while(p!=NULL ){
      cout << p->Prenom << "dans boucle" << endl;
      getch();
      if(p->Prenom==prenom) return p;
      p=p->FrereSoeurSuivant;
   }
   p=tmp;
   if(p->TeteDescendance!=NULL){
       return rechercher(prenom,p->TeteDescendance);
   }
   else return NULL;
}; 
0
mrh Messages postés 51 Date d'inscription lundi 21 janvier 2008 Statut Membre Dernière intervention 3 mars 2009
7 janv. 2009 à 11:53
Merci pour ta réponse.

La fonction que tu ma donné ne marche pas pour le cas suivant :

on a 3 frères
2 d'entre eux on des enfants
Le parcours des enfants ne se fait que sur le 1er frère le 3 ème n'est pas parcouru

impossible de trouver un enfant du 3ème frère avec ta fonction.

Donc c'est presque ça il manque un petit truc et ce sera bon.
0