首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言實現通用「讀取一行」函數:動態緩衝區自動擴展

     編輯:關於C語言

設計目標

  • 處理任意長度行 (超過固定緩衝區)
  • 正確處理 \n、\r\n、EOF 等換行風格
  • 動態分配記憶體,呼叫者負責 free
  • 錯誤/ EOF 語義清晰

完整實現碼


typedef int BOOL;
#define TRUE 1
#define FALSE 0

BOOL readLine(FILE *file, char **ppBuf) {
    const int CHUNK = 128;
    char chunk[CHUNK];
    char *accum = NULL;
    size_t accum_len = 0;
    BOOL continue_read = TRUE;

    do {
        char *res = fgets(chunk, CHUNK, file);
        if (res == NULL && !feof(file)) {  // 真正錯誤
            free(accum);
            return FALSE;
        }
        if (res == NULL) break;  // EOF

        size_t n = strlen(chunk);
        // 判斷是否讀完整行:緩衝區未滿 或 以 \n 結尾
        if (n < CHUNK - 1 || chunk[n - 1] == '\n') {
            if (n == 0) break;  // 空行 (僅可能在 EOF 前)
            continue_read = FALSE;
        }

        // 擴展累積緩衝區
        char *tmp = realloc(accum, accum_len + n + 1);
        if (!tmp) {
            free(accum);
            return FALSE;
        }
        accum = tmp;
        memcpy(accum + accum_len, chunk, n);
        accum_len += n;
        accum[accum_len] = '\0';
    } while (continue_read);

    // 移除尾部換行符
    if (accum_len > 0 && accum[accum_len - 1] == '\n') {
        accum[--accum_len] = '\0';
    }
    if (accum_len > 0 && accum[accum_len - 1] == '\r') {
        accum[--accum_len] = '\0';
    }

    if (accum_len == 0) {
        free(accum);
        *ppBuf = NULL;
        return FALSE;  // 空行或 EOF 無資料
    }

    *ppBuf = accum;
    return TRUE;
}

關鍵設計細節

使用範例


FILE *fp = fopen("large_log.txt", "r");
char *line;
while (readLine(fp, &line)) {
    printf("Line: %s\n", line);
    free(line);  // 重要!
}
fclose(fp);

與 getline() (POSIX.1-2008) 比較

細節處理方式
固定塊大小CHUNK=128,平衡系統呼叫次數與記憶體浪費
行結束判斷n < CHUNK-1 (fgets 未填滿緩衝區) 或 chunk[n-1]=='\n'
記憶體增長realloc 精確增長至 accum_len + n + 1,避免指數級增長開銷
跨平台換行依序移除 \n 再 \r,相容 Unix/Windows/Mac 格式
錯誤處理任何分配失敗/讀取錯誤釋放已分配記憶體並回傳 FALSE
擁有權移交成功時 *ppBuf 指向累積緩衝區,呼叫者必須 free
特性本實現getline()
可移植性純 C89,無相依需 POSIX 系統
記憶體策略精確增長通常倍增策略
換行符保留自動移除保留在緩衝區
錯誤碼區分簡單 TRUE/FALSE回傳讀取位元組數,-1 表錯誤/EOF

現代 Linux/BSD 系統建議直接使用 getline() 或 getdelim();嵌入式/跨平台專案可採用本實現。

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