2010-12-03 22 views
3

因此,首先,這是一項家庭作業,所以請不要爲我編寫任何代碼,只需指出我的代碼錯誤。在字符串操作/指針中找不到錯誤

該代碼的基礎是它是一個'地址/平衡'的書。我有一個結構與我的變量,但由於某種原因,我的雙鏈表變得混亂起來,我不知道如何。隨着一些花哨的(不是真正的)調試,我發現我認爲fgets(string,200,file);行會以某種方式覆蓋我的head-> name指針,這似乎會拋出其餘的代碼。相關的代碼片段在這裏:

填充列表:

void populate_list(char* filename){ 
    FILE *file = NULL; 
    char* name = NULL; 
    char* streetaddress = NULL; 
    char* city = NULL; 
    char* state = NULL; 
    char line[200]; 
    int zip; 
    float balance; 

    file = fopen(filename,"r"); 

    if(file==NULL){ 
     printf("Invalid input file\n"); 
     exit(1); 
    } 
    if(file == 0){ 
     printf("Invalid file.\n"); 
     exit(1); 
    } 

    while(!feof(file)){ 

     fgets(line, 200, file); 

     name = strtok(line, ","); 
     streetaddress = strtok(NULL, ","); 
     city = strtok(NULL,","); 
     state = strtok(NULL,","); 
     zip = atoi(strtok(NULL,",")); 
     balance = atof(strtok(NULL,",")); 

     strip_spaces(name); 
     strip_spaces(streetaddress); 
     strip_spaces(city); 
     strip_spaces(state); 

     add_node(name, streetaddress, city, state, zip, balance); 

    } 

    fclose(file); 
    return; 
} 

然後add_node代碼:

void add_node(char* name, char* streetaddress, char* city, char* state, int zip, float, balance){ 
    struct customer* addnode = NULL; 

    if(find_duplicate(name)){ 
     print_filler(1); 
     printf("DUPLICATE RECORD: %s\n", name); 
     return; 
    } else { 
     addnode = (struct customer *) malloc(sizeof(struct customer)); 
     addnode->name = name; 
     addnode->streetaddress = streetaddress; 
     addnode->city = city; 
     addnode->state = state; 
     addnode->zip = zip; 
     addnode->balance = balance; 

     if(head == NULL) { 
      head = addnode; 
      addnode->prev = NULL; 
     } else { 
      tail->next = addnode; 
      addnode->prev = tail; 
     } 

     tail = addnode; 
     addnode->next = NULL; 
    } 

    print_list(); 
    return; 
} 

的錯誤似乎第一次add_node被稱爲後要發生的事情,發生在與fgets( )第二次出發。它出於某種原因覆蓋了頭部 - >整個fgets()行的名稱。

還有其他隨機惱人的bug我還沒有固定,但這個我認爲可能是其他人的來源。

的完整代碼在這裏,如果有幫助:http://pastebin.com/k0pqyvT0

我的猜測是它的東西做的頭戴式>名稱指針通過與fgets()被覆蓋,但我不能爲我的數字生活做什麼,這是什麼,任何幫助/建議,將不勝感激。

編輯:解決方案是實現strdup()並在傳遞給add_node()時複製字符串。感謝所有的答案。

+0

第一句話的+1 – 2010-12-03 02:36:37

+0

啓動時加載的文件列表在哪裏? – jussij 2010-12-03 02:48:42

+0

該文件位於我的eclipse工作區中。我知道它正在被正確解決,問題在我的代碼中。 – Charles 2010-12-03 02:53:29

回答

1

的主要問題是,你是分配節點的你分配給點成員進入line緩衝區,並且每次調用fgets()來填充該緩衝區時都會覆蓋該緩衝區。所以每個節點中的指針總是指向同一個緩衝區(它位於堆棧上)。

該解決方案(如其他答案中所述)將使用strdup()爲每個節點成員分配要保存的每個字符串的單獨副本。因此,像這樣的工作:

.... 
} else { 
    addnode = (struct customer *) malloc(sizeof(struct customer)); 
    addnode->name = strdup(name); 
    addnode->streetaddress = strdup(streetaddress); 
    addnode->city = strdup(city); 
    addnode->state = strdup(state); 
    addnode->zip = strdup(zip); 
    addnode->balance = strdup(balance); 
    ... 
} 

這也是一個好主意,零出已分配後立即節點的內容,只是讓你沒有得到它的垃圾:

addnode = (struct customer *) malloc(sizeof(struct customer)); 
    memset(addnode, '\0', sizeof(struct customer)); 
1

我不知道它是否相關,但你的指針struct customer* addnode = NULL;是一個本地的add_node(),它不會被保存(即每次函數退出時它會被銷燬)。使用指針時爲char另外要小心,它可能似乎是直觀的字符串,但有一個疑難雜症,

所以,如果你不喜歡的東西:

while(!feof(file)) { 

    name = strtoke(string, ","); 
    // etc 

    add_node(name, ... //etc); 
} 

因爲你只即addnode->name = name,複製引用下一行讀取將取代相同的內容用作前一記錄的指針,因此您將擁有具有相同屬性的列表。

2
  1. 變量「string」是一個什麼都沒有的指針。您需要實際分配一個讀取數據的緩衝區。
  2. strtok返回一個指向原始字符串的指針,然後它會改變。如果您希望將其保留在客戶結構中,您需要分配一個新緩衝區並將字符串複製到該緩衝區中。
0

作爲黑暗獵鷹指出,你* add_node *代碼是不正確的。你需要做這樣的事情,而不是:

void add_node(char* name, char* streetaddress, char* city, char* state, int zip, float balance){ 
    struct customer* addnode = NULL; 

    strip_spaces(name); 
    strip_spaces(streetaddress); 
    strip_spaces(city); 
    strip_spaces(state); 

    if(find_duplicate(name)){ 
     print_filler(1); 
     printf("DUPLICATE RECORD: %s\n", name); 
     return; 
    } else { 
     addnode = (struct customer *) malloc(sizeof(struct customer)); 
     addnode->name = name; 
     addnode->streetaddress = streetaddress; 
     addnode->city = city; 
     addnode->state = state; 
     addnode->zip = zip; 
     addnode->balance = balance; 

     if(head == NULL) { 
      head = addnode; 
      addnode->prev = NULL; 
     } else { 
      tail->next = addnode; 
      addnode->prev = tail; 
     } 

     tail = addnode; 
     addnode->next = NULL; 
    } 

    print_list(); 
    return; 
    } 

,然後調用它像這樣:

add_node(strdup(name), strdup(streetaddress), strdup(city), strdup(state), zip, balance);