在 C 語言實現學生信息管理系統時,調用 updateStudent() 更新記錄導致文件中原有數據全部清空。根因是 fopen(filename, "wb") 以「寫入二進制」模式打開文件,**會截斷文件長度為 0** 隨後寫入,導致原數據丟失。
void updateStudent() {
FILE* fp;
if ((fp = fopen(filename, "wb")) == NULL) { // 錯誤:wb 會清空文件
// ...
}
fseek(fp, number * sizeof(Student), 0);
fwrite(&stu, sizeof(Student), 1, fp);
fclose(fp);
}
| 模式 | 含義 | 文件存在時 | 適用場景 |
|---|---|---|---|
wb | 寫入二進制 | 截斷為 0 | 創建新文件/完全重寫 |
ab | 追加二進制 | 指針在末尾 | 只在末尾添加 |
rb+ / r+b | 讀寫二進制 | 保留原內容,指針在開頭 | 隨機讀寫/更新現有記錄 |
wb+ / w+b | 讀寫二進制 | 截斷為 0 | 創建新文件並讀寫 |
void updateStudent() {
FILE* fp = fopen(filename, "rb+"); // 讀寫模式,保留原數據
if (fp == NULL) {
// 文件不存在時可嘗試 wb+ 創建,或報錯
perror("open file failed");
return;
}
fseek(fp, number * sizeof(Student), SEEK_SET);
// 讀取原記錄(可選,用於顯示/確認)
fread(&stu, sizeof(Student), 1, fp);
// 重新定位並寫入新數據
fseek(fp, number * sizeof(Student), SEEK_SET);
fwrite(&stu, sizeof(Student), 1, fp);
fclose(fp);
}
同樣使用 "wb" 導致清空。正確做法:
"rb+" 打開,fseek 定位,寫入「空記錄」(如 ID=0 或標記刪除位)。"wb" 重寫整個文件(數據量小時簡單可行)。while (!feof(fp)) { // 錯誤:feof 在讀取失敗後才置位
fread(&stu, sizeof(Student), 1, fp);
printf(...); // 會多打印一次末尾垃圾數據
}
正確寫法:
while (fread(&stu, sizeof(Student), 1, fp) == 1) {
printf(...);
}
rb+**,wb/wb+ 會清空文件。feof。