三大輸入函數對 stdin 緩衝區的處理差異是初學者頻繁踩坑的根源。
| 函數 | 讀取停止條件 | 對空白字符 | 緩衝區殘留 | 返回值 |
|---|---|---|---|---|
scanf("%s", s) | 空白 (空格/換行/Tab) | 跳過前導,遇到停止並**留在緩衝區** | 留下後續字符含換行符 | 成功轉換項數 |
gets(s) | 換行符 \n | **讀取並丟棄**換行符,不存入 | 無殘留 (換行已消費) | 字符串指針/NULL |
getchar() | 單字符 | 逐個讀取,含換行符 | 逐個消費 | 字符值/EOF |
fgets(s, n, stdin) | 換行或 n-1 字符 | **保留**換行符存入 | 無殘留 | 字符串指針/NULL |
scanf("%s", a); // 輸入 "hello\n",a="hello",緩衝區剩 "\n"
gets(b); // 直接讀到 "\n",b="" (空串),不等待輸入!
gets(c); // 這才真正等待用戶輸入
getchar() 直到 \n 或 EOF。
#define CLEAR_BUF() do { int c; while ((c=getchar())!='\n' && c!=EOF); } while(0)
fflush(stdin) (非標準,僅 MSVC 支援)。__fpurge(stdin) 或 tcflush(0, TCIFLUSH) (需 termios.h)。setbuf(stdin, NULL) 將 stdin 設為無緩衝 (影響性能,慎用)。fgets 讀整行**,再用 sscanf/strtok 解析,完全掌控緩衝區。gets (C11 已移除,緩衝區溢出風險極高)。scanf("%c", &ch) 前加空格 scanf(" %c", &ch) 跳過殘留空白。