Probleme avec une liste chainée
Voici ma structure de liste utilisé :
Code:
1 2 3 4 5 6
|
typedef struct s_list
{
int valeur;
list suiv;
} slist ; |
Voici mes methodes respective :
Code:
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
| void Insert(slist **sl, int*Val)
{
slist *tmp = NULL;
slist *csl = *sl;
slist *elem = malloc(sizeof(slist));
if(!elem) return;
elem->valeur = Val;
while(csl && csl->valeur->poid > Val->poid)
{
tmp = csl;
csl = csl->suiv;
}
elem->suiv = csl;
if(tmp) tmp->suiv = elem;
else *sl = elem;
}
t_noeud Pop(slist **sl)
{
t_noeud *Val;
t_noeud *nul;
creerNoeud(&nul);
nul = NULL;
slist *tmp;
if(!*sl) return *nul;
tmp = (*sl)->suiv;
*Val = (*(*sl)->valeur);
free(*sl);
*sl = tmp;
return *Val;
}
void Clear(slist **sl)
{
slist *tmp;
while(*sl)
{
tmp = (*sl)->suiv;
free(*sl);
*sl = tmp;
}
}
int Length(slist *sl)
{
int n=0;
while(sl)
{
n++;
sl = sl->suiv;
}
return n;
}
void View(slist *sl)
{
while(sl)
{
printf("%d\n",sl->valeur);
sl = sl->suiv;
}
} |
Maintenant quand j'effectue un parcourt sur ma liste par exemple de cette facon :
Code:
1 2 3 4
| while(sl)
{
sl = sl->suiv;
} |
L'affichage fonctionne correctement mais forcement je me retrouve en fin de liste et donc lorsque j'essaie de re afficher une seconde fois ma liste et bien cela marche pas. Comment faire pour conserver une sauvegarde du premier élément de la liste pour pouvoir remettre la liste correctement apres affichage ? J'ai essayé plusieurs choses mais j'avoue me perdre un peu dans les pointeurs...
Ou alors est-il possible de copier simplement le contenu de la liste ?
Ne te compliques tu pas un peu la vie pour rien?
Salut,
J'ai l'impression que tu te complique la vie avec des pointeurs de pointeurs pour pas grand chose...
Un simple exemple: l'insertion pourrait tres bien fonctionner en lui passant un pointeur de type slist au lieu d'une pointeur de pointeur:
Code:
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
|
/* insertion d'un élément en fin de liste
@in: début de la liste
valeur à introduire
@out: pointeur sur l'élément rajouté */
slist* Insert(slist* debut,int val)
{
/* tout ce qu'il nous faut, c'est un pointeur temporaire */
slist* temporaire=NULL;
/* dans cette fonction, il n'est pas grave de "perdre" le début de
la liste allons y gaiement ;)
recherche du dernier élément de la liste*/
while(debut->suiv!=NULL)
debut=debut->suiv;
/* création du nouvel élément */
temporaire=malloc(sizeof(slit));
/* vérification du nouvel éleme et initialisation */
if(temporaire!=NULL)
{
/* j'ai toujours peur d'oublier d'initialiser un pointeur à NULL...
je le fais donc dés que possible */
temporaire->suiv=NULL;
temporaire->valeur=val;
}
else
{
/* l'allocation a échoué... on l'indique ici à l'utilisateur */
printf("Erreur d'allocation de mémoire\n");
}
/* "yapuka" mettre transformer l'élélement rajouté en dernier élément
de la liste */
debut->suiv=temporaire;
/* et à le renvoyer */
return temporaire;
/* fini :D */
} |
La fonction clear est dans la meme veine... Allons-y
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
void Clear(slist* debut)
{
/* il nous faut un temporaire */
slist* temporaire=NULL;
while(debut!=NULL)/* je préfère toujours préciser le !=NULL plutot que d'
avoir un while (debut)...
le but du test est plus clair :P */
{
/* on récupère le suivant dans la liste */
temporaire=debut->suiv;
/* on libère correctement le premier de la liste */
debut->suiv=NULL; /* pas forcément nécessaire, mais une habitude
bonne à prendre ;) */
free(debut);
/* le temporaire devient le nouveau début */
debut=temporaire;
}
/* fini :D */
} |
Pour la fonction Length, la récursivité, j'adore ca :D
Code:
1 2 3 4 5 6 7
|
int Length(slist* travail)
{
if(travail->suivant==NULL)
return 1;
return Length(travail->suivant)+1;
} |
La fonction Pop, j'ai du mal à comprendre ce que tu veux faire... mais il *semblerait* que tu veuille pouvoir enlever le premier élément de la liste...
Si c'est ça, voilà comment je ferais:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
/* @in: début de la liste
@out: nouveau premier élément
*/
slist* Pop(slist* debut)
{
/* il nous faut un temporaire
autant lui faire prendre tout de suite la valeur du deuxieme élément*/
slist *temporaire=debut->suiv;
/* on peut maintenant supprimer debut proprement */
debut->suiv=NULL;/* les vieilles habitudes ont la peau dure ;) */
free(debut);
return temporaire;
} |
Pour View, à part que j'expliciterais le test (sous la forme de while(s1!=NULL) ), ce serait pareil...
Tiens, une petite fonction sympa...
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
/* @in: élément de la liste (début lors de l'appel)
numéro dans la liste
@out: élément de la liste
*/
slist* GetByNum(slist* travail,int index)
{
/* un pointeur temporaire */
slist* temporaire=NULL;
if(index==1)
temporaire=travail;
else
{
if(travail->suiv!=NULL)
temporaire=GetByNum(travail->suivant,--index);
else
temporaire=NULL;
}
return temporaire;
} |
Maintenant, il faut voir à utiliiser toutes ces fonctions à bon escient...
"codé en dur" cela se passerait sous la forme de
Code:
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
|
int main()
{
/* il nous faut un pointeur le début de la liste */
slist* Debut;
/* il nous faut un pointeur temporaire */
slist* temporaire;
/* et, tant qu'à faire, un pointeur sur la fin de la liste ;) */
slist* Fin;
/* insertion du premier élément
Debut=Insert(NULL,5);
/* si l'insertion a échoué, on ne sait plus rien faire */
if(Debut==NULL)
{
/*on l'affiche, et on sort */
printf("L'application va quitter\n");
return EXIT_FAILURE;
}
/* Sinon, le debut est aussi la fin */
Fin=Debut;
/* insertion d'un nouvel élément (finalement, on peut passer
directement la fin de la liste ;) )/*
temporaire=Insert(Fin, 3);
/* encore une fois, on vérifie que ca se soit bien passé */
if(temporaire==NULL)
{
/* si ce n'est pas le cas, on l'affiche, on vide la liste et on sort
mais d'autres actions pourraient etre envisagées */
printf("L'application va quitter\n");
/* on n'oublie pas de vider la liste */
Clear(Debut);
return EXIT_FAILURE;
}
/* sinon, le nouvel élément devient la fin */
Fin=temporaire
temporaire=Insert(Fin, 4);
if(temporaire==NULL)
{
printf("L'application va quitter\n");
Clear(Debut);
return EXIT_FAILURE;
}
Fin=temporaire;
temporaire=Insert(Fin, 7);
if(temporaire==NULL)
{
printf("L'application va quitter\n");
Clear(Debut);
return EXIT_FAILURE;
}
temporaire=Insert(Fin, 9);
if(temporaire==NULL)
{
printf("L'application va quitter\n");
/* on n'oublie pas de vider la liste */
Clear(Debut);
return EXIT_FAILURE;
}
Fin=temporaire;
/* affichage de la taille */
printf("%d",Length(Debut);
/* Affichage des éléments de la liste */
View(Debut);
/* Pour montrer que ca fonctionne */
View(Debut);
/* récupérer le deuxieme élément de la liste*/
temporaire=GetByNum(Debut,2);
/* et l'afficher */
printf("%d\n",temporaire->valeur);
/* vidange de la liste avant de quitter */
Clear(Debut);
/* et remise des pointeurs à 0 */
Debut=NULL;
Fin=NULL;
temporaire=NULL;
/* sortie sur un succes */
return EXIT_SUCCESS;
} |
Evidemment, rien ne t'empeche de demander à l'utilisateur d'introduire les valeurs à insérer dans la chaine... mais, ca, ce sera pour une autre réponse de ma part ;)