int ModifyList(LinkList &L, int Chinese, int Math, int English) {
LinkList p = L->next;
char changename[3]; // 緩衝區極小,姓名超 2 字符溢出
scanf("%s", changename);
for (; (strcmp(changename, p->name) == 0); p = p->next) { // 條件反了!相等時進入,不相等直接退出
p->s[0].score = Chinese;
p->s[1].score = Math;
p->s[2].score = English;
}
return OK;
}
致命錯誤:`for` 循環條件 `(strcmp(...) == 0)` 表示**當名字相等時繼續循環**,實際需**遍歷所有節點,找到匹配名字者修改**。
#define NAME_LEN 20
#define MAX_COURSES 3
int ModifyList(LinkList L, int Chinese, int Math, int English) {
char changename[NAME_LEN];
printf("請輸入要修改的學生姓名: ");
if (scanf("%19s", changename) != 1) return ERROR; // 限制寬度防溢出
LinkList p = L->next;
while (p != NULL) {
if (strcmp(changename, p->name) == 0) { // 找到匹配
p->s[0].score = Chinese;
p->s[1].score = Math;
p->s[2].score = English;
printf("修改成功: %s\n", changename);
return OK;
}
p = p->next;
}
printf("未找到學生: %s\n", changename);
return ERROR;
}
| 問題 | 原代碼 | 建議修正 |
|---|---|---|
| 姓名緩衝區過小 | `char name[3];` | `#define NAME_LEN 32` / `char name[NAME_LEN];` |
| `scanf("%s")` 無寬度限制 | `scanf("%s", p->name);` | `scanf("%31s", p->name);` (留 1 字節給 `\0`) |
| 成績輸入格式強制逗號 | `scanf("%d,%d,%d", ...)` | `scanf("%d %d %d", ...)` 支持空格/換行/逗號混合,或解析整行 `fgets`+`sscanf` |
| 無內存分配失敗檢查 | `malloc` 直接用 | `if (!p) { perror("malloc"); exit(1); }` |
| 主函數非標準 `void main()` | `void main()` | `int main(void)` 返回 `0` |
| 鏈表操作無邊界檢查 | `ListInsert(L, 2)` 位置合法性 | 檢查 `i >= 1 && i <= Length(L)+1` |
| C++ 引用語法 `LinkList &L` 用在 C 文件 | `LinkList &L` | 改 `LinkList *L` (指針的指針) 或重命名為 `.cpp` 用 C++ 編譯 |
// 完整代碼見附件,核心修正點:
// 1. 所有字符串緩衝區擴大至 32 字節
// 2. scanf 限制寬度 %31s
// 3. ModifyList 正確遍歷查找邏輯
// 4. 主函數 int main(void)
// 5. 刪除節點時免檢查 p->next 為空
// 6. 統一錯誤碼 OK/ERROR
// 7. 釋放內存後指針置 NULL (良好習慣)