| 函數 | 讀取單位 | 結束條件 | 緩衝區處理 | 安全性 |
|---|---|---|---|---|
scanf | 格式化字段 | 匹配失敗 / EOF | 留下換行符 | 低(緩衝區溢出風險) |
gets | 整行 | 換行符 / EOF | 吞掉換行符,**不檢查長度** | 極低(C11 已移除) |
getchar | 單字符 | EOF | 逐字符讀取 | 高(需自行組裝) |
int age;
char name[20];
scanf("%d", &age); // 輸入 "25\n",scanf 讀 25,\n 留在緩衝區
gets(name); // 直接讀到 \n → name 為空串!
scanf 格式字串吃掉空白(推薦)
scanf("%d", &age);
scanf(" %19[^\n]", name); // 開頭空格吃掉任意空白(含 \n),%19 防溢出
int c;
while ((c = getchar()) != '\n' && c != EOF); // 清空當前行
fgets 統一讀行 + sscanf 解析(最穩健)
char line[100];
fgets(line, sizeof(line), stdin); // 讀整行含 \n
sscanf(line, "%d", &age);
fgets(line, sizeof(line), stdin);
sscanf(line, "%19s", name); // 或用 strtok 解析
優勢:輸入與解析分離,行緩衝區大小固定,杜絕溢出,換行符自動處理。
fflush(stdin) —— 非標準,勿用fflush 僅適用於輸出流或更新流。fflush(stdin) 清空輸入緩衝區,但**不可移植**,嚴禁在跨平台代碼中使用。fgets
char buf[100];
fgets(buf, sizeof(buf), stdin); // 最多讀 99 字符 + \0
// 移除末尾 \n(若有)
buf[strcspn(buf, "\n")] = '\0';
gets**,編譯器會報警。fgets 保留 \n,需手動去除;讀滿緩衝區時不會丟失數據(下次調用繼續讀)。
#include <stdio.h>
#include <string.h>
int read_int(const char *prompt) {
char line[64];
int val;
while (1) {
printf("%s", prompt);
if (!fgets(line, sizeof(line), stdin)) return -1; // EOF
if (sscanf(line, "%d", &val) == 1) return val;
puts("Invalid integer, try again.");
}
}
void read_str(const char *prompt, char *buf, size_t sz) {
printf("%s", prompt);
fgets(buf, sz, stdin);
buf[strcspn(buf, "\n")] = '\0';
}
int main() {
int age = read_int("Age: ");
char name[20];
read_str("Name: ", name, sizeof(name));
printf("Hello %s, age %d\n", name, age);
return 0;
}
gets,改用 fgets。scanf 讀字串,改用 fgets + sscanf。scanf 可接受,但需檢查返回值並清理殘留換行符。