2012-04-16 82 views
1

代碼:ANSI C鏈接列表。 Add()函數的表現很奇怪

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

typedef struct node { 
    char* identifier; 
    char* expression; 
    struct node* next; 
} node; 

void add(node** database, char* _identifier, char* _expression, int * size) { 
    node* tmp = (node*) malloc (sizeof(node)); 
    tmp->identifier = _identifier; 
    tmp->expression = _expression; 
    tmp->next = *database; 
    *database = tmp; 
    (*size)++; 
    printf("Added: %s : %s\n", _identifier, _expression); fflush(NULL); 
} 

void show(node* database, int size) { 
    if (database == NULL) { 
     printf("Database empty\n"); 
    } 
    else { 
     node* tmp = database; 
     printf("Identifier list (%d):\n", size); fflush(NULL); 
     while (tmp != NULL) { 
      printf("%s : \"%s\" \n", tmp->identifier, tmp->expression);fflush(NULL); 
      tmp = tmp->next; 
     } 
    } 
} 

int main() { 
    node* database = NULL; 
    int size = 0; 
    add(&database, "a1", "abc", &size); 
    add(&database, "a2", "def", &size); 
    add(&database, "a3", "ghi", &size); 

    char identifier[20]; 
    char expression[1000]; 
    int i; 
    for (i = 0; i<3; i++) { 
     scanf("%s %s", identifier, expression); 
     add(&database, identifier, expression, &size); 
    } 
    show(database, size); 
    printf ("Bye!"); 
    return 0; 
} 

「添加」功能效果很好手動調用的時候,但它並沒有在循環裏工作,從標準輸入讀取數據。以下是一次運行的結果:

Added: a1 : abc 
Added: a2 : def 
Added: a3 : ghi 
a4 mno 
Added: a4 : mno 
a5 ghi 
Added: a5 : ghi 
a6 kml 
Added: a6 : kml 
Identifier list (6): 
a6 : "kml" 
a6 : "kml" 
a6 : "kml" 
a3 : "ghi" 
a2 : "def" 
a1 : "abc" 
Bye! 

正如您所看到的節點a1,a2,a3已正確添加到列表中。但是,在正確添加到列表後,a4和a5在添加a6後更改爲全部「a6」。 我花了一天的時間,但我無法弄清楚。任何人?

回答

2

你的問題是它們都指向相同的指針:identifier。 (也是expression)。 (儘管第3增加了指向分離const char*小號靜態初始化。)

要解決這一點,你需要爲每個新元素動態分配空間添加(與malloc EG)和釋放他們(與free如)當您刪除它們。

e.g:

void add(node** database, char* _identifier, char* _expression, int * size) { 
    node* tmp = (node*) malloc (sizeof(node)); 
    tmp->identifier = (char *)malloc(strlen(_identifier)); 
    strcpy(tmp->identifier, _identifier); 
    tmp->expression = (char *)malloc(strlen(_expression)); 
    strcpy(tmp->expression, _expression); 
    tmp->next = *database; 
    *database = tmp; 
    (*size)++; 
    printf("Added: %s : %s\n", _identifier, _expression); fflush(NULL); 
} 

你必須確保這些資源是在一些點correspondignly發佈,否則將有內存泄漏。

+0

哦sh * t爲什麼我沒有想到這一點。謝謝你的哥們。 – 2012-04-16 17:41:54

2

嗯...因爲你是存儲指針而不是字符串的副本?

您每次都在存儲「標識符」和「表達式」的地址,因此鏈表上的所有3個項目都指向相同的數據。

+0

我想是的,我不太習慣ANSI C,缺乏真正的字符串類型真的讓我發瘋。謝謝你向我展示了這個錯誤。 – 2012-04-16 17:43:35