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

C 語言學生籍貫資料管理系統:修改/刪除後輸出異常的根因與修正

     編輯:程式設計綜合問答

問題現象

執行修改或刪除操作後,呼叫 allselect() 輸出全部資料時,開頭出現學號 -842150451、姓名 屯屯屯屯屯屯、籍貫 屯屯屯屯屯屯 的垃圾資料,每操作一次多一筆。

根本原因

鏈結串列節點刪除/修改邏輯錯誤,導致未正確釋放記憶體或指標斷裂,殘留未初始化的記憶體區塊被誤讀。 具體常見錯誤:

  • jgdelete 刪除節點後,未將前一節點的 next 指向被刪節點的 next,造成鏈斷,遍歷時跑到野指標區域。
  • jgedit 修改時誤用 malloc 建立新節點卻未插入鏈表,舊節點未釋放。
  • 結構體陣列/鏈表未初始化,TotalSco、AveSco 等欄位含隨機值 (如 0xCCCCCCCC 解釋為 -842150451)。

修正策略

  1. 統一節點操作函式:將搜尋、刪除、修改封裝為獨立函式,確保指標操作正確。
  2. 刪除節點標準流程:
    Node* prev = find_prev(head, target_id);
    if (prev && prev->next) {
        Node* del = prev->next;
        prev->next = del->next;
        free(del);
    }
    
  3. 修改節點就地更新:找到節點後直接修改其欄位,**不要**重新 malloc。
  4. 初始化所有欄位:建立節點時以 memset(&node, 0, sizeof(Node)) 或逐欄位賦值。
  5. 輸出函式加入防呆:
    
    void allselect(Node* head) {
        Node* p = head;
        while (p) {
            if (p->id > 0) { // 簡易過濾垃圾資料
                printf("%d %s %s\n", p->id, p->name, p->native);
            }
            p = p->next;
        }
    }
    

完整修正範例 (關鍵片段)


// 刪除
void jgdelete(Node** head, int id) {
    Node *cur = *head, *prev = NULL;
    while (cur && cur->id != id) { prev = cur; cur = cur->next; }
    if (!cur) return; // 找不到
    if (prev) prev->next = cur->next;
    else *head = cur->next;
    free(cur);
}

// 修改
void jgedit(Node* head, int id) {
    Node* cur = head;
    while (cur && cur->id != id) cur = cur->next;
    if (!cur) return;
    printf("請輸入新姓名 籍貫: ");
    scanf("%s %s", cur->name, cur->native);
}

除錯建議

  • 使用 valgrind --leak-check=full 偵測記憶體洩漏/非法存取。
  • 在 allselect 中印出節點位址 %p,觀察是否出現重複/異常位址。
  • 改用陣列或 std::vector (C++) 簡化管理,除非教學要求鏈結串列。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved