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

C語言文件操作與哈夫曼編碼:fwrite/fread雙向序列化字符指針數組避坑指南

     編輯:程式設計綜合問答

代碼中`HuffmanCode HC`定義為`char**`(字符指針數組),寫入時用`fwrite(HC[i], sizeof(char), strlen(HC[i])+1, fp)`逐個寫入字符串,**但讀取時未為`HC[i]`分配內存**,導致`fread`寫入野指針崩潰。本文解析雙向序列化正確流程。

核心問題


// 寫入:正確
for (int i = 1; i <= n; i++)
    fwrite(HC[i], sizeof(char), strlen(HC[i]) + 1, fp); // 寫入字符串含\0

// 讀取:錯誤
for (int i = 1; i <= n; i++)
    fread(HC[i], sizeof(char), strlen(HC[i]) + 1, fp); // HC[i] 未分配內存!野指針寫入

正確讀取流程:先分配、後讀取、長度前置

因字符串長度不定,**必須在文件中存儲長度**,讀取時先讀長度,再分配,再讀內容。

寫入端(長度前置)


for (int i = 1; i <= n; i++) {
    int len = strlen(HC[i]) + 1; // 含\0
    fwrite(&len, sizeof(int), 1, fp);       // 1. 寫入長度
    fwrite(HC[i], sizeof(char), len, fp);   // 2. 寫入字符串
}

讀取端(分配後讀)


// 假設 HC 已分配指針數組:HC = (char**)malloc((n+1) * sizeof(char*));
for (int i = 1; i <= n; i++) {
    int len;
    if (fread(&len, sizeof(int), 1, fp) != 1) break; // 讀長度
    HC[i] = (char*)malloc(len);                      // 關鍵:分配內存!
    if (HC[i] == NULL) { /* 錯誤處理 */ }
    if (fread(HC[i], sizeof(char), len, fp) != len) { /* 錯誤處理 */ }
}

完整哈夫曼編碼文件存儲結構建議


// 文件頭
struct HuffmanFileHeader {
    int n;              // 葉子節點數/編碼數量
    int maxCodeLen;     // 最大編碼長度(可選)
    // 保留字節...
};

// 數據區:n 條記錄
// 每條:int len; char code[len];

內存管理鐵律

  1. 誰分配,誰釋放:讀取時`malloc`的`HC[i]`,使用完畢必須逐個`free(HC[i])`,最後`free(HC)`。
  2. 檢查返回值:`malloc`/`fread`/`fwrite`均需檢查返回值。
  3. 二進制文件跨平台隱患:`int`大小、字節序、結構體對齊可能不同。跨平台交換建議用文本格式(JSON/文本協議)或標準序列化庫(Protocol Buffers、FlatBuffers)。

調試技巧

  • 寫入後用十六進制編輯器查看文件:長度(4字節) + 字符串內容,循環n次。
  • 讀取時打印每次讀到的`len`和字符串前幾字符,驗證同步正確。
  • Valgrind/AddressSanitizer檢測野指針寫入/內存洩漏。
序列化指針數組鐵律:文件存長度,讀取先malloc,嚴格對稱,內存有借有還。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved