Veuillez consulter le code complet ci-dessous.
J'ai un tableau initial nommé arr
.
J'utilise une liste liée pour stocker certains index via la fonction append
. Après avoir obtenu les indices, je les stocke dans une liste chaînée et utilise clearList
pour changer les valeurs correspondantes à 0 (dans cet exemple arr [2] et arr [4]).
Enfin, je libère la mémoire en appelant freeList
car j'ai fini avec la liste chaînée.
Cependant, pour pouvoir faire la même chose encore et encore, je dois mettre head
à NULL chaque fois que j'appelle freeList
. Mais je ne peux pas. Aucune idée sur la façon de résoudre ça?
Merci.
#include <stdio.h> #include "gurobi_c.h" #include <stdlib.h> //Gurobi variables GRBenv *env = NULL; GRBmodel *model = NULL; //Gurobi variables struct Node { int data; struct Node *next; struct Node *end; }; void append(struct Node** head_ref, int new_data) { struct Node *last = *head_ref; struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); new_node->data = new_data; new_node->next = NULL; new_node->end = new_node; if (*head_ref == NULL) { *head_ref = new_node; //printf(" ..Init Append %d\n",new_data); return; } last = (*head_ref)->end; last->next = new_node; (*head_ref)->end=new_node; //printf(" ..Append %d\n",new_data); return; } void clearList(struct Node *node, double *arr) { int i; if(node!=NULL) { struct Node tmp; tmp=*(node->end); while (node != NULL) { i=node->data; arr[i]=0; //printf(" ..clear %d \n", node->data,(node->end)->data); node = node->next; } } } void freeList(struct Node *node) { struct Node *tmp,*hd; hd=node; while (node != NULL) { tmp=node; node = node->next; //printf(" ..Free %d \n", tmp->data); free(tmp); } hd=NULL; } int main (){ Node *head; double *arr = (double *) malloc(sizeof(double) * 10); for(int i=0;i<10;i++) arr[i]=i; head=NULL; printf("Head: %s\n", head); append(&head,2); append(&head,4); clearList(head,arr); for(int i=0;i<10;i++) printf("No %d : %.2f\n",i,arr[i]); freeList(head); free(arr); printf("%s", head); getchar(); return 0; }
3 Réponses :
J'ai réalisé qu'il était possible de changer la fonction freeList
afin qu'elle renvoie une valeur NULL. Voir le code mis à jour ci-dessous:
#include <stdio.h> #include "gurobi_c.h" #include <stdlib.h> //Gurobi variables GRBenv *env = NULL; GRBmodel *model = NULL; //Gurobi variables struct Node { int data; struct Node *next; struct Node *end; }; void append(struct Node** head_ref, int new_data) { struct Node *last = *head_ref; struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); new_node->data = new_data; new_node->next = NULL; new_node->end = new_node; if (*head_ref == NULL) { *head_ref = new_node; //printf(" ..Init Append %d\n",new_data); return; } last = (*head_ref)->end; last->next = new_node; (*head_ref)->end=new_node; //printf(" ..Append %d\n",new_data); return; } void clearList(struct Node *node, double *arr) { int i; if(node!=NULL) { struct Node tmp; tmp=*(node->end); while (node != NULL) { i=node->data; arr[i]=0; //printf(" ..clear %d \n", node->data,(node->end)->data); node = node->next; } } } Node* freeList(struct Node *node) { struct Node *tmp; while (node != NULL) { tmp=node; node = node->next; printf(" ..Free %d \n", tmp->data); free(tmp); } return NULL; } int main (){ Node *head; double *arr = (double *) malloc(sizeof(double) * 10); for(int i=0;i<10;i++) arr[i]=i; head=NULL; printf("Head: %s -> null as expected\n", head); append(&head,2); append(&head,4); clearList(head,arr); for(int i=0;i<10;i++) printf("No %d : %.2f\n",i,arr[i]); printf("Head: %s -> Not null as linkedlist is not freed\n", head); head=freeList(head); printf("Head: %s -> Again null as expected\n", head); free(arr); printf("%s", head); getchar(); return 0; }
A part: Pourquoi le cast inutile dans new_node = (struct Node *) malloc (sizeof (struct Node))
? Considérez new_node = malloc (sizeof * new_node)
. arr = malloc (sizeof * arr * 10);
etc. à la place. Plus facile à coder correctement, à réviser et à maintenir.
Je pense que la solution d'idk est meilleure car rien ne vous empêche d'appeler freeList (head);
ou même (void) freeList (head);
dans votre code.
Vous modifiez déjà la valeur de head dans votre fonction append
, vous devez donc faire la même chose dans freeList
:
void freeList(struct Node **head_ref) { struct Node *tmp,*node; node=*head_ref; while (node != NULL) { tmp=node; node = node->next; //printf(" ..Free %d \n", tmp->data); free(tmp); } *head_ref=NULL; } int main (){ /* do stuff */ freeList(&head); /* do stuff */ }
Juste pour être complet: une autre option possible serait d'utiliser une macro wrapper pour freeList()
.
void freeList(struct Node *node) { /* ... */ } #define freeListNull(node) do { \ freeList(node); \ node = NULL; \ } while(0) int main () { /* ... */ freeListNull(head); /* ... */ }
Cette solution a un inconvénient similaire à la version qui renvoie le pointeur modifié. Vous pouvez simplement oublier d'utiliser le bon appel freeListNull (head);
et appeler freeList (head);
à la place. La meilleure solution est une fonction freeList ()
qui prend l'adresse du pointeur head
comme dans la réponse d'idk.
Comment changer la valeur de
head
lors de l'ajout? Peut-être que cette méthode pourrait également être utilisée pour la suppression ...Je ne change pas la valeur de la tête, elle reste toujours la même. J'ajoute uniquement de nouveaux nœuds à la liste.
Si vous ne changez jamais la valeur de
head
, ce seraitNULL
et votre liste serait vide ... donc votre fonctionappend
doit changer ça en quelque sorteCorrect. Je fais cela par
head_ref
dansappend
. Cependant, dansfreeList
, je libère la tête, ce qui complique la situation.Si vous passiez l'adresse de
head
àfreeList
, vous pouvez la définir sur NULL dansfreeList
. Sinon, vous devrez fairehead = NULL;
après avoir appeléclearList
. Vous pouvez également créer une macro de préprocesseur, par exempleclearListNull
qui fait les deux.@Bodo Pourriez-vous expliquer comment faire cela exactement s'il vous plaît? Mon problème est que je sais que cela pourrait être fait en manipulant des adresses, mais je ne peux pas le faire fonctionner. Je trouve un peu une solution alternative mais j'aimerais apprendre à bien faire les choses.