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

C語言文件/標準I/O函數家族大對比:fgets vs gets, fgetc vs getc, scanf 族詳解

     編輯:關於C語言

函數聲明速查 (Glibc 2.3.6)

函數組聲明流參數
fgets/fputschar *fgets(char *s, int n, FILE *stream);
int fputs(const char *s, FILE *stream);
需指定 FILE*
gets/putschar *gets(char *s);
int puts(const char *s);
隱式 stdin/stdout
getchar/putcharint getchar(void);
int putchar(int c);
隱式 stdin/stdout
fgetc/fputcint fgetc(FILE *stream);
int fputc(int c, FILE *stream);
需指定 FILE*
getc/putcint getc(FILE *stream);
int putc(int c, FILE *stream);
需指定 FILE*
fscanf/scanf/sscanfint fscanf(FILE *stream, const char *fmt, ...);
int scanf(const char *fmt, ...);
int sscanf(const char *s, const char *fmt, ...);
文件/標準輸入/字符串

關鍵差異深度解析

1. fgets vs gets —— 安全性的分水嶺

  • fgets(s, n, stream):讀取最多 n-1 字符,**保留換行符 \n**,防止緩衝區溢出。**首選函數**。
  • gets(s):**無長度限制**,遇換行符停止並**丟棄 \n**,極易導致緩衝區溢出,**C11 標準已移除**,嚴禁使用。
  • 配對原則:fgets 讀入保留 \n,fputs **不自動添加 \n**;gets 丟棄 \n,puts **自動添加 \n**。混用會導致換行數量錯亂。

2. 函數 vs 宏:fgetc/fputc vs getc/putc/getchar/putchar

  • fgetc/fputc 是真函數:有地址,可作函數指針,代碼體積小,調用有函數開銷。
  • 其餘均為宏 (Glibc 中定義為 __STDIO_INLINE 或 #define):預處理展開,執行效率略高,但增加代碼體積,無法取地址。
  • getchar() 等價 getc(stdin),putchar(c) 等價 putc(c, stdout)。
  • 宏實現內部調用 _IO_getc_unlocked 等無鎖版本,需注意線程安全(通常由上層 flockfile 保護)。

3. 字符 vs 字符串輸入:getchar vs fgets

  • getchar:逐字符讀取,返回 int(為了容納 EOF 這一負值),適合逐字符處理。
  • fgets/gets:按行讀取字符串,適合文本行處理。

4. 掃描族:scanf / fscanf / sscanf

  • scanf(fmt, ...):從 stdin 讀取。
  • fscanf(stream, fmt, ...):從指定文件流讀取。
  • sscanf(str, fmt, ...):從內存字符串 解析,**不涉及 I/O**,極其適合字符串解析(如 HTTP 請求、配置文件行解析)。
  • 共享格式字符串語法,但 sscanf 不受流狀態影響,更安全可控。

最佳實踐建議

  1. 輸入首選 fgets + sscanf:fgets 安全讀行,sscanf 解析,徹底避免 scanf 留在緩衝區的換行符導致後續讀取異常。
  2. 單字符處理用 getchar/fgetc,區分 EOF 與有效字符(返回值用 int 接收)。
  3. 輸出用 fputs/fputc/fprintf 顯式指定流,避免隱式 stdout 依賴。
  4. 禁用 gets,編譯器會報警;禁用 scanf("%s", buf) 無寬度限制讀字符串。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved