2017-03-25 2 views
0

J'ai beaucoup cherché, avant que je demande cela, mais je ne peux pas obtenir ce petit morceau de code au travail.
Je sais que l'utilisation d'un global pointer (ou variable) est considéré comme une mauvaise pratique (au lieu de passer par référence) mais je suis obligé d'utiliser cette pratique malheureusement.Pointeur global (tête de liste liée) pas mis à jour correctement

Ce que je suis en train de faire est de faire un linked list qui se compose de noeuds (struct avec quelques informations), et après chaque insert() la liste est étendu de façon dynamique par un node (à moins que l'élément en question existe déjà, dans ce cas, le membre name est remplacé).
Le pointeur next des points à l'élément suivant dans la list (c'est là que je cède le nouveau nœud de malloc()

Le programme compile correctement et exécute avec la sortie suivante:.
retrieve returned: (NULL) à chaque printf() appel
C'est pourquoi je crois que le pointeur global (tête de la liste) n'est pas mis à jour correctement

Je suis désolé pour cette question naïve mais je n'arrive pas à trouver où l'affectation/affectation se passe mal ,
Quoi qu'il en soit, merci d'avance pour votre aide.

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

struct node{ 
    char *id; 
    char *name; 
    struct node *next; 
}; 
struct node* list; //list head 
struct node* p; //pointer to list head 

char *retrieve(char *id){ 
    if(list == NULL) 
     return NULL; //list is empty, no element to return. 
    for(p = list; p != NULL; p = p->next) 
     if(strcmp(id, p->id) == 0) 
      return p->name; 
    return NULL; 
} 

void insert(char *id, char *name){ 
    int exists = 0; 
    struct node* temp = NULL; 
    for(p = list; p != NULL; p = p->next){ 
     if(strcmp(id, p->id) == 0){ //id already exists, overwrite with the new name. 
      free(p->name); 
      p->name = strdup(name); 
      exists = 1; 
      break; 
     } 
    } 
    if(exists) return; 
    //insert at the end of the list 
    temp = malloc(1 * sizeof(struct node)); 
    if(temp == NULL){ 
     printf("memory allocation failed\n"); 
     return; 
    } 
    temp->id = strdup(id); 
    temp->name = strdup(name); 
    temp->next = NULL; 
    p = temp; 
    return; 
} 

int main(){ 
    struct node* temp = NULL; 
    p = NULL; 
    list = NULL; 
    insert("145a","Jim"); 
    insert("246b","Alice"); 
    insert("322c","Mike"); 
    printf("retrieve returned: %s\n\n", retrieve("145a")); 
    printf("retrieve returned: %s\n\n", retrieve("246b")); 
    printf("retrieve returned: %s\n\n", retrieve("322c")); 
    p = list; 
    while(p != NULL){ // node deletion starting from first to last element. 
     free(p->id); 
     free(p->name); 
     temp = p; 
     p = p->next; 
     free(temp); 
    } 
    return 0; 
} 
+0

'pour {' après loop, p sera NULL. Le 'p = temp;' après ne fera rien. – wildplasser

+0

@wildplasser J'ai essayé de trouver le nœud vide (certains -> next-> next .... levels ahead) pour y assigner le nouveau – hitter

+0

L'utilisation d'un pointeur vers un pointeur simplifierait votre programme (et pourrait aussi éviter la référence codée en dur) à la variable globale) – wildplasser

Répondre

1
void insert(char *id, char *name) 
{ 
    struct node *temp = NULL, **pp; 
     /* Pointer to pointer points to the global */  
    for(pp = &list; *pp ; pp = &(*pp)->next){ 
     if(strcmp(id, (*pp)->id)) continue; 

     free((*pp)->name); 
     (*pp)->name = strdup(name); 
     return; 
     } 

    //insert at the end of the list 
    temp = malloc(sizeof *temp); 
    if(!temp){ 
     printf("memory allocation failed\n"); 
     return; 
    } 
    temp->id = strdup(id); 
    temp->name = strdup(name); 
    temp->next = NULL; 
    *pp = temp; 
    return; 
} 

Et vous pouvez même le faire sans le pointeur temp *: (! P = liste; p = NULL; p = p> suivante)

void insert(char *id, char *name) 
{ 
    struct node **pp; 

    for(pp = &list; *pp ; pp = &(*pp)->next){ 
     if(strcmp(id, (*pp)->id)) continue; 
      free(p->name); 
      p->name = strdup(name); 
      return; 
     } 
    // pp now points to the terminal NULL pointer 
    *pp = malloc(sizeof **pp); 
    if(!*pp){ 
     printf("memory allocation failed\n"); 
     return; 
    } 
    (*pp)->id = strdup(id); 
    (*pp)->name = strdup(name); 
    (*pp)->next = NULL; 
    return; 
} 
+0

Je pensais que c'était sizeof (struct node *) pas sizeof (* temp), ehm .... non? – hitter

+0

Ils sont tous les deux corrects, mais le mien est plus résistant aux accidents. – wildplasser

0

Vous n'initialisez list autre qu'avec NULL. En conséquence,

char *retrieve(char *id){ 
    if(list == NULL) 
     return NULL; 

retourne toujours NULL.

+0

merci d'avoir répondu, Inside insert J'essaie d'élargir la liste d'un noeud, en créant un nouveau noeud et l'assigner à 'p' qui pointe vers le noeud suivant vide de la' liste ' – hitter

+0

Fondamentalement, j'essaie de trouver à quel noeud le' list' est vide (null) et assigner là, c'est pourquoi j'utilise le pointeur 'p' – hitter

+0

Pourriez-vous s'il vous plaît, mettre à jour la réponse pour montrer l'affectation correcte, après le passage à la fin de la 'liste'? Je serais heureux de l'accepter dans ce cas. – hitter