[c] liste simplement chainé==> pb [résolu==> merci]

liste simplement chainé==> pb [résolu==> merci] [c] - C - Programmation

Marsh Posté le 16-03-2007 à 22:37:27    

Bonjour,
J'ai un problème avec ceci :

Code :
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef struct liste
  4. {
  5. int x;
  6. struct liste* next;
  7. }liste;
  8. void ajouteFin(liste *l,int b) /* ajoute un element en fin de liste*/
  9. {
  10. liste *a;
  11. a=malloc(sizeof(liste));
  12. a->x=b;
  13. l->next=a;
  14.         a->next=NULL;
  15. }
  16. void ajouteDebut(liste *l,int b)/* ajoute element en début de liste*/
  17. {
  18. liste *a;
  19. a=malloc(sizeof(liste));
  20. a->x=b;
  21. a->next=l;
  22. l=a;/*pb */
  23. }
  24. int main()
  25. {
  26. liste *l=NULL;
  27. l=malloc(sizeof(liste));
  28. if(l!=NULL)
  29. {
  30.  l->x=1;
  31.  l->next=NULL;
  32.  ajouteDebut(l,4);
  33. }
  34. free(l);
  35. return 0;
  36. }


 
Il ne s'agit que de la manipulation de liste chainé.Le problème ce situe au niveau de l'ajout en début de liste.La procédure ne marche pas ( erreur de segmentation à l'execution) mais je ne comprend pas pourquoi.
Je pense avoir identifié le pb ( au niveau de l'affectation l=a), mais je ne comprend pas pourquoi ça foire.
 
Si quelqu'un avait la gentillesse de m'aider ....
 
 
Pour info, compilé avec gcc 4.1.2 sous ubuntu edgy eft.
Merci d'avance

Message cité 1 fois
Message édité par castorgris le 18-03-2007 à 18:21:50
Reply

Marsh Posté le 16-03-2007 à 22:37:27   

Reply

Marsh Posté le 16-03-2007 à 22:42:33    

pour modifier un pointeur, il est de bon aloi d'utiliser un pointeur de pointeur :o
 
Ta fonction ajouteDebut ne modifie en rien ta liste dans ton main

Reply

Marsh Posté le 16-03-2007 à 22:48:25    

Un pointeur de pointeur ? c'est quoi cet animal ?  
Dois-je ecrire :
 
void ajouteDebut(liste **l,int b)
?

Message cité 1 fois
Message édité par castorgris le 16-03-2007 à 22:56:41
Reply

Marsh Posté le 16-03-2007 à 23:08:00    

Je te signale aussi que ta fonction ajouteFin ne fonctionne pas non plus. (en plus de ne pas initialiser a->next à NULL).
Il faut tester le retour des malloc et enfin, en C, on ne caste pas les malloc.

Message cité 1 fois
Message édité par Trap D le 16-03-2007 à 23:09:45
Reply

Marsh Posté le 16-03-2007 à 23:14:50    

Trap D a écrit :

Je te signale aussi que ta fonction ajouteFin ne fonctionne pas non plus. (en plus de ne pas initialiser a->next à NULL).
 


Effectivement, mais c'est juste un couper coller malheureux

 
Trap D a écrit :


Il faut tester le retour des malloc


C'est à dire?

 


le castage ( heu... ça existe ?) des malloc vient aussi d'un oubli de modif du code pour repassage de c++ en c parcque pour une raison que j'ignore, un printf("%d", (l->next)->next) me donne une erreur de segmentation, mais pas un cout << (l->next)->x, sur les compilateur de mon ecole.


Message édité par castorgris le 16-03-2007 à 23:20:13
Reply

Marsh Posté le 16-03-2007 à 23:54:01    

Tu peux fort bien ne plus avoir de mémoire à ta disposition, aussi l'alllocation mémoire peut échouer et la fonction malloc te renvoie NULL. Donc, il faut tester le retour.

Reply

Marsh Posté le 17-03-2007 à 12:35:04    

castorgris a écrit :

Un pointeur de pointeur ? c'est quoi cet animal ?  
Dois-je ecrire :
 
void ajouteDebut(liste **l,int b)
?


http://mapage.noos.fr/emdel/notes. [...] e_variable
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 17-03-2007 à 22:32:11    

castorgris a écrit :

Bonjour,
J'ai un problème avec ceci :

Code :
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef struct liste
  4. {
  5. int x;
  6. struct liste* next;
  7. }liste;
  8. void ajouteFin(liste *l,int b) /* ajoute un element en fin de liste*/
  9. {
  10. liste *a;
  11. a=malloc(sizeof(liste));
  12. a->x=b;
  13. l->next=a;
  14.         a->next=NULL;
  15. }
  16. void ajouteDebut(liste *l,int b)/* ajoute element en début de liste*/
  17. {
  18. liste *a;
  19. a=malloc(sizeof(liste));
  20. a->x=b;
  21. a->next=l;
  22. l=a;/*pb */
  23. }
  24. int main()
  25. {
  26. liste *l=NULL;
  27. l=malloc(sizeof(liste));
  28. if(l!=NULL)
  29. {
  30.  l->x=1;
  31.  l->next=NULL;
  32.  ajouteDebut(l,4);
  33. }
  34. free(l);
  35. return 0;
  36. }



Très gros problème de conception dans ce code
1) dans le main, tu fais "l=malloc()" => ok
2) ensuite, tu fais "ajouteDebut(l, 4) et dans la fonction "ajouteDebut", tu cherches à faire "a=malloc()" puis "l=a" => donc tu remplaces le résultat de ton malloc initial par le second malloc => t'as perdu ton pointeur initial !!!
Accessoirement, comme l'a dit Joel F, pour modifier une variable dans une fonction, il faut passer l'adresse de cette variable à la fonction qui la stocke dans un pointeur sur cette variable. Donc si tu veux modifier "l" qui est de type "liste *", tu dois passer "&l" à ta fonction qui la stockera dans un "liste **". Ensuite, dans ta fonction "ajouteDebut()", chaque fois que tu veux t'adresser à ton pointeur, tu dois utiliser "*l". Mais de toute façon, même si tu écris correctement ta fonction d'un point de vue syntaxique, tu planteras ton programme car tu perdras ton malloc initial.
 
Question: Pourquoi faire plein de malloc ? Pourquoi ne pas adopter un comportement "objet" qui serait "j'écris une fonction qui alloue de la mémoire et me remplis mon élément avec ma valeur et qui me renvoie l'adresse allouée" puis faire "j'appelle cette fonction quand j'ne ai besoin et j'insère l'élément alloué là où il faut"
 
Par exemple un truc de ce style

Code :
  1. liste* remplir(int val)
  2. {
  3.     liste* elem;
  4.     elem=malloc(sizeof(liste));
  5.     if (elem == NULL)
  6.       return NULL;
  7.     elem->x=val;
  8.     elem->next=NULL;
  9.     return elem;
  10. }
  11. void ajouteDebut(liste** maListe, liste* elem)
  12. {
  13.      if (*maListe == NULL)
  14.      {
  15.           *maListe=elem;
  16.           return;
  17.      }
  18.       elem->next=(*maListe);
  19.       *maListe=elem;
  20. }
  21. void ajouteFin(liste** maListe, liste* elem)
  22. {
  23.      liste *cur;
  24.      if (*maListe == NULL)
  25.      {
  26.           *maListe=elem;
  27.           return;
  28.      }
  29.      for (cur=(*maListe); cur->next != NULL; cur=cur->next);
  30.      cur->next=elem;
  31. }
  32. void videListe(liste* maListe)
  33. {
  34.     liste* cur;
  35.     if (maListe == NULL)
  36.        return;
  37.     for (cur=maListe->next; cur != NULL; cur=cur->next)
  38.     {
  39.          free(maListe);
  40.          maListe=cur;
  41.      }
  42. }
  43. int main()
  44. {
  45.       liste* l=NULL;
  46.       liste* elem;
  47.       elem=remplir(4);
  48.       if (elem != NULL)
  49.       {
  50.           ajouteDebut(&l, elem);
  51.           videListe(l);
  52.       }
  53.       return 0;
  54. }


 
C'est déjà un bon début. Ensuite, je ferais une différenciation entre "type élément" et "type liste" en créant des conteneurs spécialisés pour chacun. Ainsi, je pourrais manipuler plus facilement la liste en elle-même et/ou chaque élément qui la compose. Et je pourrais agrémenter la liste d'autres trucs utiles comme par exemple "nb d'éléments" ou "premier et dernier" ou autres outils...


Message édité par Sve@r le 17-03-2007 à 22:35:04

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 18-03-2007 à 18:21:09    

Merci de passer du temps sur ça.
Ce petit bout de code est un exercie pour nous apprendre à manipuler des pointeurs.
Après moult tentative, j'en suis arrivé à  

Code :
  1. liste * ajouteDebut(liste* l, int valeur)
  2. {
  3.     liste* tmp = malloc(sizeof(liste));
  4.     tmp->x = valeur;
  5.     tmp->next = l;
  6.     return tmp;
  7. }


 
qui marche sans pb.Maiis j'ai changais d'approche par rapport à ce que j'avais ecrit au début.
Par contre je ne gère pas la liberation mémoire de tmp.
 
Merci pour ta solution sve@r, qui me semble bien plus "propre" et   moins maladroite .
 
Il faut que j'apprenne à utiliser l'approche objet du langage, parceque moi j'ai tendance à ecrire du code parfois fonctionnel ( souvent non ...) en barbare, surtout que l'usage que j'ai ( et que j'aurais)  est un usage "calcul".Je ne coderais jamais une application, mais des fonctions d'integration numérique si .
 
Merci pour l'aide.
je repasserais surement bientôt pour un autre problème ....

Reply

Marsh Posté le 18-03-2007 à 23:18:36    

castorgris a écrit :


parceque moi j'ai tendance à ecrire du code parfois fonctionnel


 
Le mot que tu cherche, c'est pas plutôt "impérative" ;) ?
 
http://fr.wikipedia.org/wiki/Progr [...] ctionnelle
http://fr.wikipedia.org/wiki/Progr [...] 3%A9rative
 
:)

Reply

Marsh Posté le 18-03-2007 à 23:18:36   

Reply

Marsh Posté le 18-03-2007 à 23:32:23    

castorgris a écrit :

Il faut que j'apprenne à utiliser l'approche objet du langage


http://mapage.noos.fr/emdel/tad.htm


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 19-03-2007 à 07:24:21    


 
Par fonctionnel je voulais dire "qui marche"...

Reply

Marsh Posté le 19-03-2007 à 07:24:54    


 
 
Merci.Dès que j'ai un moment de libre j'irais voir.


Message édité par castorgris le 19-03-2007 à 07:25:11
Reply

Marsh Posté le 19-03-2007 à 16:17:30    

castorgris a écrit :

Merci de passer du temps sur ça.
Ce petit bout de code est un exercie pour nous apprendre à manipuler des pointeurs.
Après moult tentative, j'en suis arrivé à  

Code :
  1. liste * ajouteDebut(liste* l, int valeur)
  2. {
  3.     liste* tmp = malloc(sizeof(liste));
  4.     tmp->x = valeur;
  5.     tmp->next = l;
  6.     return tmp;
  7. }


 
qui marche sans pb.


 
Ca marche sans problème à condition que, dans la fonction appelante, tu imposes que ta liste récupère ce que renvoie ta fonction "ajouteDebut" sinon ton début ne changera pas. C'est un défaut de conception car ta fonction qui est sensée ajouter un élément au début de la liste ne le fait en fait pas. C'est ta façon de récupérer ce qu'elle renvoie qui fera que ça marche ou pas...
 
Je vais te donner un début de code. Essaye de le comprendre pour le compléter ensuite avec les fonctions qui t'intéressent...

typedef struct elem {
    int x;
    struct elem *next;
} t_elem;
 
typedef struct {
    t_elem *debut;
} t_liste;
 
void listeInit(t_liste *liste)
{
    liste->debut=NULL;
}
 
int main()
{
    t_liste maListe;
    listeInit(&maListe);
 
    return 0;
}


Message édité par Sve@r le 19-03-2007 à 16:18:56

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed