first->prev->prev = NULL; // ici et ensuite je ne maîtrise plus
first vient d'être créé par init() donc first->prev est obligatoirement à NULL et on ne peut déréférencer NULL -> plantage.
Même remarque pour le plantage de appbeg()
Globalement, le code est difficile à suivre. La première raison est qu'il se base sur la même structure de données pour représenter la liste (struct dlist *) et pour représenter les maillons de la liste (struct dlist). Pourtant, conceptuellement, ce sont deux choses différentes et dans le code il n'apparait pas à l'évidence si un struct dlist * est la liste ou un pointeur sur un maillon.
Il faut les différentier ce qui permettra aussi de faire apparaitre dans la représentation de la liste les particularités de celle-ci (par exemple un pointeur sur le dernier maillon facilitera grandement la fonction append().
Faire ceci demande de revisiter le code actuel, Autant le faire maintenant alors que le code n'est pas trop volumineux, tu y gagneras beaucoup ensuite en simplicité et clarté. C'est un bon investissement !
Pour t'aider dans cette voie, une trame possible peut être :
1 2 3 4 5 6 7 8 9 10 11
| typedef struct maillon
{
int i;
struct maillon *prev;
struct maillon *next;
} Maillon;
typedef struct
{
Maillon * first;
Maillon * last;
} Liste; |
La fonction init(), qui crée la liste, devrait créer une liste vide. C'est logique. Par sa fonction, son nom devrait être changé.
1 2 3 4 5 6 7 8 9 10
| Liste * creerListe(void)
{
Liste * p= malloc(sizeof *p); // ou si on préfère malloc(sizeof(Liste))
if(p!= NULL)
{
p->first = NULL;
p->last = NULL;
}
return p;
} |
A noter que dans cette configuration, il n'est pas obligatoire d'allouer la liste dynamiquement. On peut avoir pour la créer Liste liste = {NULL, NULL};.
Il sera peut être préférable de faire aussi une fonction Maillon * creerMaillon(int val).
Ta fonction print() affiche en fait un maillon, elle devient :
1 2 3 4
| void printMaillon( Maillon * p)
{
printf("%d %p %p\n", p->i, p->prev, p->next);
} |
à différentier d'une fonction qui afficherait la liste :
1 2 3 4 5 6 7 8 9 10 11 12
| void printListe(Liste * liste)
{
if(liste != NULL)
{
Maillon * p = liste->first;
while(p != NULL)
{
printMaillon(p);
p = p->next;
}
}
} |
La fonction append() prend pour prototype Maillon * append( Liste * liste, int val). Elle sera beaucoup plus simple à écrire (et à relire) du fait du champ last dans Liste. Sa trame sera :
- Créer un maillon en utilisant la fonction creerMaillon(). La fonction retourne p.
- Si la création a échoué (p==NULL), sortir en retournant p (qui est NULL, c'est
ce NULL qui indiquera l'échec de l'append())
- Sinon
- Si la liste est vide (liste->last==NULL), mettre dans liste->first et
liste->last l'adresse du maillon (p) et sortir en retournant l'adresse p
du maillon (p!= NULL ce qui indiquera le succès de l'append())
- Sinon, ajouter le maillon en queue :
- placer dans l'actuel dernier maillon de la liste (d'adresse liste->last) le champ
next sur p
- placer dans p->prev l'adresse de l'actuel dernier maillon
- changer l'adresse du dernier maillon de la liste (liste->last) par celle
du nouveau maillon de queue (p)
- sortir en retournant l'adresse p du maillon (pour indiquer le succès de
l'append())
[codes non testés]
Partager