scanf("%s", str) 遇到空白字符 (空格、制表符、換行) 即停止,無法讀取含空格的字符串。
char str[100];
scanf("%[^\n]", str); // 讀到換行符停止
getchar(); // 關鍵:吸收殘留在緩衝區的 \n
scanf("%99[^\n]", str) 限制寬度
char str[100];
fgets(str, sizeof(str), stdin);
// 移除末尾換行符 (若有)
size_t len = strlen(str);
if (len > 0 && str[len-1] == '\n') str[len-1] = '\0';
char str[100];
int i = 0, ch;
while ((ch = getchar()) != '\n' && ch != EOF && i < 99)
str[i++] = ch;
str[i] = '\0';
| 維度 | scanf %[^\n] | fgets | getchar 循環 |
|---|---|---|---|
| 安全性 | 需手動限寬 | ✅ 自動限長 | 需手動限長 |
| 換行符處理 | 殘留需吸收 | 保留在字符串中 | 不包含換行符 |
| 靈活性 | 高 (掃描集) | 低 (整行讀取) | 極高 (逐字符) |
| 推薦場景 | 簡單交互、格式解析前 | 生產代碼、文件讀取 | 教學、特殊解析 |
scanf("%d", &n); fgets(s, 100, stdin); → fgets 讀到殘留 \n。getchar() 或用 scanf(" %[^\n]", s) (前導空格吃空白)。
gets(str); 無長度檢查,必導致緩衝區溢出漏洞。scanf("%[0-9]", s); 輸入 "abc" → 返回 0,'a' 留在緩衝區。while(getchar()!='\n'); 清行。
// 讀整數後安全讀行
int n;
char line[1024];
scanf("%d", &n);
getchar(); // 吸收換行
fgets(line, sizeof(line), stdin); // 讀完整行
line[strcspn(line, "\n")] = '\0'; // 通用去換行
// 或純 scanf 掃描集
scanf("%d", &n);
scanf(" %1023[^\n]", line); // 前導空格吃空白,限寬 1023
生產代碼首選 fgets:安全、標準、無殘留問題。交互式簡單輸入用 scanf 掃描集:配合寬度限制和前導空格。徹底拒絕 gets。理解輸入流緩衝機制(行緩衝、字符殘留)是避免輸入 Bug 的關鍵。