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

C 語言檔案操作教程(十):字串讀寫函數 fgets/fputs 詳解與範例

     編輯:C 語言基礎

字串導向的檔案 I/O:fgets / fputs

相較於字元級 fgetc/fputc 與格式化 fscanf/fprintf,fgets/fputs 以行為單位處理文字檔,適合逐行讀取、記錄日誌、配置檔解析。

fgets — 讀取一行至緩衝區


char *fgets(char *str, int n, FILE *stream);
  • 最多讀取 n-1 個字元,遇到 \n、EOF 或滿 n-1 停止。
  • 讀入的 \n 會被保留 在緩衝區末尾 (後接 \0)。
  • 成功回傳 str,失敗/EOF 回傳 NULL。

範例:讀取檔案前 10 字元 (含換行)


#include 
#include 

int main(void)
{
    FILE *fp;
    char str[11];   /* 容納 10 字元 + \0 */

    if ((fp = fopen("e10_1.c", "rt")) == NULL) {
        printf("Cannot open file strike any key exit!");
        getch();
        return 1;
    }

    fgets(str, 11, fp);      /* 讀最多 10 字元 */
    printf("%s", str);       /* 直接輸出,含換行 */

    fclose(fp);
    getch();
    return 0;
}

fputs — 寫入字串至檔案


int fputs(const char *str, FILE *stream);
  • 寫入字串至檔案,不自動加 \n (與 puts 不同)。
  • 成功回傳非負值,失敗回傳 EOF。

範例:以附加模式寫入字串並驗證


#include 
#include 

int main(void)
{
    FILE *fp;
    char ch, st[20];

    if ((fp = fopen("string", "at+")) == NULL) {
        printf("Cannot open file strike any key exit!");
        getch();
        return 1;
    }

    printf("input a string:\n");
    scanf("%19s", st);       /* 限制長度防溢位 */
    fputs(st, fp);           /* 寫入檔案末尾 */

    rewind(fp);              /* 移回檔案開頭 */
    ch = fgetc(fp);
    while (ch != EOF) {
        putchar(ch);
        ch = fgetc(fp);
    }
    printf("\n");

    fclose(fp);
    getch();
    return 0;
}

關鍵差異對照

特性fgetsfputsgets/puts (標準 I/O)
自動加 \n保留輸入的 \n不加gets 丟棄 \n,puts 自動加 \n
緩衝區溢位保護有 (n-1 限制)N/A (僅寫入)gets 無保護 (極危險,C11 已移除)
檔案指標需 FILE*需 FILE*stdin/stdout
二進位檔適用是 (但會在 \0 停止)是否

常見陷阱與最佳實務

  1. fgets 讀到 \n 保留 \n:若需移除,手動處理 str[strcspn(str, "\n")] = '\0';。
  2. 檢查回傳值:while (fgets(buf, sizeof buf, fp)) 是標準逐行讀取慣用語。
  3. 文字 vs 二進位模式:Windows 文字模式會將 \r\n 轉為 \n,影響 ftell 位置計算;二進位模式 "rb"/"wb" 保持原貌。
  4. 避免混用 fgets 與 fscanf:殘留換行符會導致 fscanf 讀取異常;若需混用,中間插 fgetc 吃掉換行或改用 fgets + sscanf。
  5. 大檔案逐行處理:fgets 記憶體占用固定 (緩衝區大小),適合串流處理超大日誌檔。

現代替代方案

  • C++:std::getline(std::ifstream, std::string) 自動管理記憶體、無長度限制。
  • POSIX:getline(&buf, &len, fp) 自動擴充緩衝區 (C 標準庫擴展)。
  • C11 Annex K:fgets_s 邊界檢查版本 (MSVC 支援)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved