Pour le moment, ta liste ne peut stocker que des int. Je dirais qu’on peut améliorer ton code de ce point de vue, et le rendre plus générique, avec la structure suivante :
typedef struct list
{
void *content;
size_t size;
struct list *next;
} list;
Ou tu remplaces le content par ce que tu veux : un pointeur sur une structure, une chaîne de caractère, etc… Le champ size est alors utile pour savoir la taille de ce qui est stocké en mémoire pour en faire une copie, etc…
Ce code, plus générique, nécessite d’autres fonctions plus souples pour travailler avec, et ce avec des pointeurs sur fonction pour une véritable modularité. Par exemple, ton code d’affichage deviendrait :
Si tu stockes des chaînes de caractère dans tes maillons (par exemple), ça donnera :
void print_string(list *lst)
{
printf("Contenu: [%.*s]\n", lst->size, (char *)(lst->content));
}
/* on l'utilise ainsi dans le code : */
lst_print(ma_liste_de_strings, &print_string);
Ce code te permet de faire une bibliothèque vraiment modulable que tu n’auras pas besoin de retoucher par la suite. Il y aurait d’autres choses à faire, mais partir sur un code plus modulable est déjà un bon début, je crois. C’est là qu’on voit que les pointeurs sur fonction, c’est la vie. (Je me suis fait une bibliothèque personnelle pour utiliser les listes chaînées, je peux te l’envoyer si tu veux).
Je l’ai faite hier et ce matin à partir d’une autre que j’avais déjà faite. Je pense qu’elle est fonctionnelle, avec toutes les fonctionnalités couramment utiles. Si tu trouves un beug, je veux bien que tu le signales.
C’est un manque total d’imagination de ma part : ce sont mes initiales. Et j’ai l’habitude de tout préfixer pour éviter de tomber sur des noms de fonction / macros déjà existants. Une des fonctionnalités introduites par le C++ qui me “manque” le plus en C est les namespaces
T’as vu, le code n’est pas trop compliqué ? Et on peut l’utiliser avec n’importe quoi. D’ailleurs, je pense faire la même chose, mais avec un arbre binaire balancé ; ou encore un tableau dynamique qui se redimensionne automatiquement quand on ajoute des éléments. Je pourrais en faire une version avec la contiguïté en mémoire, et une autre sans. Enfin je verrai quand je m’ennuierai.
Eh bien ça dépend : si c’est non contigu, ça ne coûte pas grand’ chose, c’est un simple tableau de pointeurs qu’on redimensionne de temps en temps quand on ajoute des éléments.
L’avantage de ressources contiguës, c’est qu’on peut se déplacer avec le pointeur, genre :
// declaration du pointeur begin sur le premier element
for (size_t i = 0 ; i < len ; ++i)
{
// on utilise begin + i
}
Ici, ça ne sert à rien, mais quand par exemple on le passe en paramètre à une fonction, on peut écrire pointeur + 1 sans risque puisque les données sont contiguës.