Pourquoi ne puis-je pas append correctement à une liste chaînée lors de l’utilisation d’une fonction?

J’essaie de créer une liste chaînée. Lorsque j’ajoute à la liste dans la même fonction que celle dans laquelle je crée l’object, cela fonctionne.

Définitions:

typedef struct student { int num; char* name; } student; typedef struct container { student* data; struct container* next; } container ; 

Tous les objects que j’utilise sont initialisés comme ceci:

 student stu1; stu1.num = 6; stu1.name = "grefagf"; front = createContainer(&stu1); back = front; student stu2; stu2.num = 3; stu2.name = "dsghjyreawre"; student stu3; stu3.num = 4; stu3.name = "dsghhjrant"; student stu4; stu4.num = 213; stu4.name = "fdsafgrw"; 

Quand j’ajoute ces éléments à une liste dans la fonction principale comme ceci:

 container* tmp; tmp = createContainer(&stu2); back->next = tmp; back = tmp; tmp = createContainer(&stu3); back->next = tmp; back = tmp; tmp = createContainer(&stu4); back->next = tmp; back = tmp; 

cela fonctionne correctement, en affichant ceci:

 1: 6 grefagf 2: 3 dsghjyreawre 3: 4 dsghhjrant 4: 213 fdsafgrw 

quand je l’imprime en utilisant une autre fonction que j’ai faite.

Mais si je crée une fonction appelée add() et passe stu2, stu3 …, comme ceci:

 int add(student to_add) { container* tmp; tmp = createContainer(&to_add); printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name); back->next = tmp; back = tmp; return 1; } 

faites alors ceci dans la fonction principale:

 add(stu2); add(stu3); add(stu4); 

il affiche ceci:

 1: 6 grefagf 2: 41096808 fdsafgrw 3: 41096808 fdsafgrw 4: 41096808 fdsafgrw 

Voici la source au cas où vous en auriez besoin:

Exemple non fonctionnel: https://pastebin.com/ZLqTzp4t

 #include  #include  typedef struct student { int num; char* name; } student; typedef struct container { student* data; struct container* next; } container ; container* back; container* front; container* createContainer(student* data) { container* tmp = malloc(sizeof(container)); tmp->data = data; tmp->next = NULL; return tmp; } void printList(container* front) { container* tmp = front; int i; i=0; while (tmp != NULL) { i++; printf("%d:\t%d\t\t%s\n", i, tmp->data->num, tmp->data->name); tmp = tmp->next; } } int main(void) { student stu1; stu1.num = 6; stu1.name = "grefagf"; front = createContainer(&stu1); back = front; student stu2; stu2.num = 3; stu2.name = "dsghjyreawre"; student stu3; stu3.num = 4; stu3.name = "dsghhjrant"; student stu4; stu4.num = 213; stu4.name = "fdsafgrw"; container* tmp; tmp = createContainer(&stu2); back->next = tmp; back = tmp; tmp = createContainer(&stu3); back->next = tmp; back = tmp; tmp = createContainer(&stu4); back->next = tmp; back = tmp; printf("front\n"); printList(front); printf("\ntop\n"); printList(back); return EXIT_SUCCESS; } 

Exemple de fonction: https://pastebin.com/TyQY4j5k

 #include  #include  typedef struct student { int num; char* name; } student; typedef struct container { student* data; struct container* next; } container ; container* back; container* front; container* createContainer(student* data) { container* tmp = malloc(sizeof(container)); tmp->data = data; tmp->next = NULL; return tmp; } int add(student to_add) { container* tmp; tmp = createContainer(&to_add); printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name); back->next = tmp; back = tmp; return 1; } void printList(container* front) { container* tmp = front; int i; i=0; while (tmp != NULL) { i++; printf("%d:\t%d\t\t%s\n", i, tmp->data->num, tmp->data->name); tmp = tmp->next; } } int main(void) { student stu1; stu1.num = 6; stu1.name = "grefagf"; front = createContainer(&stu1); back = front; student stu2; stu2.num = 3; stu2.name = "dsghjyreawre"; student stu3; stu3.num = 4; stu3.name = "dsghhjrant"; student stu4; stu4.num = 213; stu4.name = "fdsafgrw"; add(stu2); add(stu3); add(stu4); printf("front\n"); printList(front); printf("\ntop\n"); printList(back); return EXIT_SUCCESS; } 

OK j’ai essayé ça marche. Obtenez uniquement les structures d’étudiant par adresse à votre fonction d’ajout comme ci-dessous

 add(&stu2); add(&stu3); add(&stu4); 

et changez la fonction de add comme ci-dessous

 int add(student *to_add) { container* tmp; tmp = createContainer(to_add); printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name); back->next = tmp; back = tmp; return 1; } 

Voici une version plus ou moins minimale de votre code avec la fonction add . Il fonctionne à 60 lignes contre 83 pour votre original.

 #include  #include  typedef struct student { int num; char *name; } student; typedef struct container { student *data; struct container *next; } container; static container *back; static container *front; static container *createContainer(student *data) { container *tmp = malloc(sizeof(container)); tmp->data = data; tmp->next = NULL; return tmp; } static void add(student to_add) { container *tmp = createContainer(&to_add); printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name); back->next = tmp; back = tmp; } static void printList(container *item) { for (int i = 0; item != NULL; item = item->next) printf("%d:\t%d\t\t%s\n", ++i, item->data->num, item->data->name); } int main(void) { student stu1 = { 6, "grefagf" }; student stu2 = { 3, "dsghjyreawre" }; student stu3 = { 4, "dsghhjrant" }; student stu4 = { 213, "fdsafgrw" }; front = createContainer(&stu1); back = front; add(stu2); add(stu3); add(stu4); printf("front\n"); printList(front); printf("\nback\n"); printList(back); return EXIT_SUCCESS; } 

Sur mon Mac, cela a produit:

 added: (3, dsghjyreawre) added: (4, dsghhjrant) added: (213, fdsafgrw) front 1: 6 grefagf 2: 0 3: 0 4: 0 back 1: 0 

Le problème est que vous transmettez l’adresse d’une variable locale à votre fonction createContainer() , mais que cette variable sort de la scope de votre conteneur et que son conteneur pointe ainsi sur garbage. Comme cela appelle un comportement indéfini, les résultats peuvent être différents sur votre ordinateur et les deux seront corrects. Un crash est également possible – c’est l’une des beautés de UB.

Vous devez le réviser de deux manières. createContainer() effectue une copie de ce qui est transmis ou vous pouvez transférer des pointeurs vers les variables de main() via add() à createContainer() . Ce code est le second – mais ce n’est probablement pas la meilleure solution à long terme. Cependant, il y a (beaucoup) plus de gestion de mémoire à gérer pour une solution générale qui copie ce qui a été passé.

 #include  #include  typedef struct student { int num; char *name; } student; typedef struct container { student *data; struct container *next; } container; static container *back; static container *front; static container *createContainer(student *data) { container *tmp = malloc(sizeof(container)); tmp->data = data; tmp->next = NULL; return tmp; } static void add(student *to_add) { container *tmp = createContainer(to_add); printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name); back->next = tmp; back = tmp; } static void printList(container *item) { for (int i = 0; item != NULL; item = item->next) printf("%d:\t%d\t\t%s\n", ++i, item->data->num, item->data->name); } int main(void) { student stu1 = { 6, "grefagf" }; student stu2 = { 3, "dsghjyreawre" }; student stu3 = { 4, "dsghhjrant" }; student stu4 = { 213, "fdsafgrw" }; front = createContainer(&stu1); back = front; add(&stu2); add(&stu3); add(&stu4); printf("front\n"); printList(front); printf("\nback\n"); printList(back); return EXIT_SUCCESS; } 

Il y a 5 caractères différents ici de la dernière version. Il y a un * dans la définition de la fonction de add() ; il n’y a pas de & dans l’appel à createContainer() ; il y a un & dans chacun des appels à add() dans main() . Le résultat est:

 added: (3, dsghjyreawre) added: (4, dsghhjrant) added: (213, fdsafgrw) front 1: 6 grefagf 2: 3 dsghjyreawre 3: 4 dsghhjrant 4: 213 fdsafgrw back 1: 213 fdsafgrw 

Ce code perd de la mémoire car il ne tente pas de nettoyer la liste. C’est bon pour le moment. Sachez simplement que vous devrez éventuellement nettoyer.

La fonction add doit également consumr la liste liée (ou “conteneur”) à laquelle elle ajoute “étudiant”.

Ainsi, vous ne devriez pas créer un conteneur “temporaire”, mais utiliser le conteneur passé dans et append à l’arrière de celui passé dans le conteneur.

EDIT: Vous venez de réaliser que votre dos et votre face sont globaux. Ce n’est probablement pas une bonne idée, car de cette façon, vous ne pouvez avoir qu’une seule liste chaînée pour l’ensemble de votre programme.

Relire maintenant …

EDIT 2: Ahh c’était un bon. Vous passez en étudiant (ce qui en fait une copie), puis vous prenez son adresse dans la fonction add, qui est l’adresse d’une variable de la stack. La stack est éjectée, donc l’adresse aux variables de la stack n’a pas de sens. Au lieu de cela, add devrait prendre un pointeur vers un étudiant et vous devez donner l’adresse de stu2, stu3, etc.

EDIT 3: Ahh trop tard 🙁