首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言鏈表刪除節點與打印異常的根因修復

     編輯:程式設計綜合問答

問題現象

  • `creat()` 中打印正常,單獨調用 `print()` 無輸出/亂碼。
  • `remove()` 刪除邏輯錯誤,導致鏈表斷裂/內存洩漏。

核心根因

頭指針傳遞方式錯誤。C 語言參數傳值,`creat(EXAMPLE* head)` 內部 `head = malloc(...)` 只修改副本,主函數的 `head` 仍為未初始化野指針。需傳遞**指針的指針** (`EXAMPLE** head`) 或返回新頭指針。

修正代碼

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

typedef struct Node {
    int data;
    struct Node* next;
} Node;

// 1. 創建:傳遞頭指針地址
void create(Node** head) {
    Node *p, *pre = NULL;
    int n, val;
    printf("節點數: "); scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        printf("值: "); scanf("%d", &val);
        p = (Node*)malloc(sizeof(Node));
        p->data = val; p->next = NULL;
        if (*head == NULL) *head = p;
        else pre->next = p;
        pre = p;
    }
}

// 2. 打印:傳遞頭指針值即可
void print(Node* head) {
    for (Node* p = head; p; p = p->next)
        printf("%d ", p->data);
    printf("\n");
}

// 3. 刪除:刪除首個負值節點及其後所有節點
void remove_neg(Node** head) {
    Node *cur = *head, *pre = NULL;
    
    // 找到首個負值節點
    while (cur && cur->data >= 0) {
        pre = cur;
        cur = cur->next;
    }
    if (!cur) return; // 無負值
    
    // 斷開並釋放
    Node* toFree = cur;
    if (pre) pre->next = NULL; // 中間斷開
    else *head = NULL;         // 頭節點即負值
    
    while (toFree) {
        Node* nxt = toFree->next;
        free(toFree);
        toFree = nxt;
    }
}

int main() {
    Node* head = NULL;
    create(&head);
    print(head);      // 正常
    remove_neg(&head);
    print(head);      // 正常
    
    // 釋放剩餘
    while (head) {
        Node* t = head;
        head = head->next;
        free(t);
    }
    return 0;
}

關鍵修正對比

原代碼問題修正
`void create(Node* head)`頭指針修改不回傳`void create(Node** head)` + `*head = malloc`
`head = malloc` 在函數內主函數 head 不變主函數傳 `&head`,函數寫 `*head`
`remove` 邏輯混亂未正確斷開、釋放、處理頭節點先找負值節點,記錄前驅,斷開後批量釋放
`print` 獨立調用失敗傳入的 head 是野指針創建正確後自動正常

調試技巧

  1. **打印指針地址**:`printf("head=%p\n", (void*)head);` 對比主/被調用函數地址是否一致。
  2. **Valgrind/AddressSanitizer**:`gcc -fsanitize=address -g` 編譯,自動檢測野指針、雙重釋放、內存洩漏。
  3. **畫圖推演**:紙上畫節點、指針、操作步驟,比單憑腦補可靠得多。

總結

C 語言鏈表操作**頭指針必須傳址**(`Node**` 或返回 `Node*`),否則創建函數無法修改調用者的頭指針。刪除操作要分「找目標」「斷鏈」「釋放」三步,特別注意頭節點被刪除的情況。掌握這兩點,鏈表增刪改查不再出錯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved