C 語言提供多套字符/行輸入函數,來源不同 (標準庫/擴展庫)、行為迥異 (回顯/緩衝/長度限制)。本文徹底區分 7 大函數,給出選型決策樹與安全建議。
函數族譜總覽
| 函數 | 頭文件 | 標準 | 來源 | 回顯 | 緩衝 | 長度限制 | 返回值 |
getch() | <conio.h> | ❌ 非標準 | 控制台直接讀取 | ❌ 無 | 無緩衝 (即時) | 單字符 | int 字符碼 |
getche() | <conio.h> | ❌ 非標準 | 控制台直接讀取 | ✅ 有 | 無緩衝 | 單字符 | int 字符碼 |
getchar() | <stdio.h> | ✅ C89 | stdin (標準輸入流) | ✅ 有 | **行緩衝** (需回車) | 單字符 | int 字符碼/EOF |
fgetc() | <stdio.h> | ✅ C89 | 任意 FILE* 流 | 視流而定 | 視流而定 | 單字符 | int 字符碼/EOF |
getc() | <stdio.h> | ✅ C89 | 任意 FILE* (宏/函數) | 同 fgetc | 同 fgetc | 單字符 | 同 fgetc |
fgets() | <stdio.h> | ✅ C89 | 任意 FILE* | 視流而定 | 視流而定 | ✅ n-1 字符 | char* / NULL |
gets() | <stdio.h> | ❌ C11 移除 | stdin | ✅ 有 | 行緩衝 | ❌ 無 | char* / NULL |
關鍵差異深度解析
1. conio.h 族 : 非標準、Windows 專屬、游戲/舊教學常見
getch():無回顯,**無需回車即時返回**,常用「老闆鍵」、密碼輸入、菜單選擇
getche():有回顯,其餘同 getch
- 移植性極差: Linux/Unix 無
conio.h,**現代代碼禁用**
2. stdio.h 字符輸入 : 標準、跨平台
getchar() ≡ fgetc(stdin) ≡ getc(stdin) (宏展開)
- **行緩衝**:輸入字符存入內核缓冲區,**回車才交付程序**,用戶可輸入多字符但函數僅取首字符
fgetc/getc 通用於文件/管道/網絡流
3. stdio.h 行輸入 : 安全性分水嶺
- fgets(buf, n, stream):讀至換行或
n-1 字符,**保留 \n**,自動補 \0,**唯一推薦的安全行讀取**
- gets(buf):**無長度檢查**,緩衝區溢出元兇 (Morris 蠕蟲利用點),**C11 標準已刪除,絕對禁用**
EOF 處理規範
int ch = fgetc(fp);
while (ch != EOF) { // EOF 為 -1 (stdio.h 定義)
putchar(ch);
ch = fgetc(fp);
}
- 文本模式下
EOF 可靠表示文件結束
- 二進制模式下字節值可能為 0xFF (-1),**必須用
feof(fp) / ferror(fp) 區分**
對應輸出函數族
| 輸入 | 輸出 | 關係 |
fgetc | fputc | 基礎函數 |
getc | putc | 宏/函數封裝 |
getchar | putchar | #define putchar(c) fputc(c, stdout) |
fgets | fputs | 行讀寫,fputs 不自動加 \n |
gets | puts | puts 相當 fputs(s, stdout) + \n |
選型決策樹
- 需跨平台/標準合規 → **只用
<stdio.h> 族**
- 讀單字符、非交互/文件流 →
fgetc/getc
- 交互式讀單字符 (接受行緩衝) →
getchar
- **讀整行/字符串 →
fgets(buf, sizeof(buf), stdin) (唯一正解)**
- 舊代碼維護
getch/getche → 逐步替換為平台抽象層或 getchar + 終端設置
- 上一篇文章: C 語言 scanf 函數完全指南:格式字串、輸入陷阱與最佳實務
- 下一篇文章: C 語言陣列作為函數參數:值傳遞、位址傳遞與實戰陷阱
Copyright ©
程式碼之家 All Rights Reserved