2014-06-25 55 views
-1

我試圖在輸入'+ word'的地方創建程序,並且它添加了單詞,並且當您輸入'-word'時,它將該單詞從鏈接列表中取出。從鏈接列表中刪除項目時出現分段錯誤

插入這個詞對我來說工作正常,但刪除它會導致分段錯誤。我不確定錯誤在哪裏。另外,有沒有一種方法可以讓你知道分段錯誤的位置?

void 
remove_from_list(struct linked_list *list, char *data) 
{ 
    struct node *current_node = list->head; 
    struct node *previous_node = NULL; 

    while (current_node != NULL) { 
     if (current_node->data == data) { 
      break; 
     } 
     previous_node = current_node; 
     current_node = current_node->next; 
    } 
    if (previous_node == NULL) { 
     list->head = list->head->next; 
    } else { 
     previous_node->next = current_node->next; 
    } 
    free(current_node); 
    if (list->tail == current_node) 
     list->tail = previous_node; 
} 

int 
main(void) 
{ 
    struct linked_list list = { .head = NULL, .tail = NULL }; 
    char word[50]; 

    do { 
     printf("Enter string: "); 
     fgets(word, 50, stdin); 
     if (word[0] == '+') 
      add_to_list(&list, word); 
     else if (word[0] == '-') 
      remove_from_list(&list, word); 
    } while (word[0] != '\n'); 

    print_list_rec(&list); 
    free_list(&list); 
    return 0; 
} 
+0

您應該使用實際的字符串比較(如'strncmp')來查找節點是否包含您的字符串。所有這一切:'current_node-> data == data'是比較指針。 – turbulencetoo

+0

因爲C中的字符串很棘手,如果僅從內存管理的角度來看,可能會嘗試使用相同的代碼,但將整數看作'data',看看你是否得到相同的問題。 – turbulencetoo

+0

關於這一行:free_list(&list);,你不能釋放堆棧上的一個結構體,但是,你可以遍歷鏈表,釋放列表中的每個節點(除了第一個節點以外,因爲它在堆棧中) – user3629249

回答

1

您遇到seg故障的主要原因是因爲您不處理在嘗試刪除時沒有列表中數據的情況。

if (previous_node == NULL) { 
    list->head = list->head->next; 
} else { // ------------------------- If at the end of the list you go in here 
    previous_node->next = current_node->next; 
} 

current_nodeNull所以current_node->next賽格故障。

您到列表末尾的原因是因爲您沒有正確比較字符串的數據。使用strcmp()像@this建議正確比較。但是你應該處理沒有列表中的數據的情況。


你可以在中間添加while循環檢查和第一個if語句,這將處理列表中的一個空表,數據未 -

if(current_node == NULL) // Empty list or wasn't found 
    return; 

另注:

在檢查是否是尾部之前,您可以免費current_node。顛倒這個順序。

上的其他人說什麼頂
if (list->tail == current_node) 
    list->tail = previous_node; 
free(current_node); 
1

您環路你們的末日鏈表,然後進行解引用一個NULL指針這裏

} else { 
    previous_node->next = current_node->next; 
} 

這是因爲你比較不實際的比較數據;

if (current_node->data == data) { 

,你永遠不會得到真正的結果出來,如果語句。

如果要比較字符串,請使用strcmp()。

0

,如果列表是空的,這個代碼將導致段:

if (previous_node == NULL) { 
    list->head = list->head->next; 
} 
0

沒有爲插入功能是很難的代碼說什麼錯,因爲刪除lool的步驟確定。但是,插入時可能會出現問題,因此無法正常工作。

但是在代碼中存在一個問題,其中如果您嘗試刪除不存在的節點,您仍然會最終刪除最後一個節點。你需要在while循環中斷處設置一個標誌,然後只有在標誌爲真時才移除節點。

+0

注意:最後一個節點如果數據不在列表中,它將不會被刪除 - 當嘗試訪問current_node-> next時它會發生錯誤,並且不需要標誌,只需要檢查'current_node'是否爲'Null' –

0

功能應該看看下面的方式

void 
remove_from_list(struct linked_list *list, char *data) 
{ 
    struct node *current_node = list->head; 
    struct node *previous_node = NULL; 

    while (current_node != NULL && strcmp(current_node->data, data) != 0) 
    { 
     previous_node = current_node; 
     current_node = current_node->next; 
    } 

    if (current_node != NULL) 
    { 
     if (previous_node != NULL) 
      previous_node->next = current_node->next; 
     else 
      head = head->next; 

     if (list->tail == current_node) 
      list->tail = previous_node; 

     free(current_node->data); 
     free(current_node); 
    } 
} 

此外,我將存儲沒有前導+或字符串 - 。在這種情況下,如果聲明主要將如下

if (word[0] == '+') 
     add_to_list(&list, word + 1); 
    else if (word[0] == '-') 
     remove_from_list(&list, word + 1); 

否則你將永遠不會發現,與添加一個字符串加號,從列表中刪除。

+0

應該使用strcmp()來比較字符串。 –

+0

@Andrew_CS哦,是的。:) –

相關問題