無數初學者在 `scanf`、`getchar`、`gets`、`cin` 面前翻車:明明寫了兩次輸入,程序卻只停一次;字符串輸入莫名其妙被截斷;循環輸入第二輪直接跳過。本文從緩衝區原理出發,系統拆解各函數行為差異,給出通用解決方案。
所有鍵盤輸入先進「輸入緩衝區」(stdin),輸入函數從中讀取數據,**而非直接讀鍵盤**。緩衝區殘留數據會導致後續讀取函數「誤以為已有輸入」而跳過等待。
| 函數 | 讀取對象 | 結束條件 | 對結束符處理 | 是否接收空格 |
|---|---|---|---|---|
| scanf("%c") | 單字符 | 任意字符 | **保留** \n 於緩衝區 | 是(含空格/換行) |
| getchar() | 單字符 | Enter | **保留** \n 於緩衝區 | 是 |
| scanf("%s") | 字符串 | 空格/Tab/換行 | **丟棄** 結束符 | 否(遇空格停止) |
| gets() | 字符串 | 換行 | **丟棄** \n | **是**(整行) |
char ch1, ch2;
scanf("%c", &ch1); // 輸入 'a' + Enter
scanf("%c", &ch2); // 直接讀到殘留的 '\n',不等待!
// ch1='a'(97), ch2='\n'(10)
原因: 第一次讀取字符後,\n 滯留緩衝區,第二次直接讀走。
char s1[20], s2[20];
scanf("%s", s1); // 輸入 "Hello world"
scanf("%s", s2); // 直接讀到 "world",不等待!
// s1="Hello", s2="world"
gets(str1); // "Hello world" 完整讀入 gets(str2); // 正常等待下一行
cin.get(); // 返回 int,讀單字符,**保留 \n** cin.get(char &ch); // 讀入 ch,**保留 \n** cin.get(char *buf, n); // 讀 n-1 字符或遇 \n,**丟棄 \n**
// C while (getchar() != '\n'); // 丟棄當前行剩餘 // C++ cin.ignore(numeric_limits::max(), '\n'); // 丟棄至換行
// C: fgets + sscanf char line[256]; fgets(line, sizeof(line), stdin); sscanf(line, "%d %s", &a, str); // C++: getline + stringstream string line; getline(cin, line); stringstream ss(line); ss >> a >> str;