原始题目

以下代码的输出是什么?

int a;
cin >> a;
string s;
getline(cin, s);
cout << "[" << s << "]";

输入:

42
hello
  • A. [hello]
  • B. []
  • C. [ hello]
  • D. [42]

答案:B([]


为什么不是 A:>> 会留下一个换行符

这是 cin >>getline 混用的经典陷阱

关键在缓冲区里残留的内容:

  1. cin >> a 读到 42 后就停了——它读到数字结尾就认为读取完成,换行符 \n 仍然留在输入缓冲区里
缓冲区: "42\nhello\n"
          ↑↑   ↑↑↑↑↑↑↑↑↑
         读走   残留:"\nhello\n"
  1. getline(cin, s) 从当前位置开始读,第一个字符就是那个残留的 \n——它认为“这一行已经结束了”,于是读到一个空字符串就返回。

  2. 真正的 hello 还在缓冲区里,根本没被读到。

所以输出是 [ + 空串 + ],即 [],选 B

选项 C [ hello] 是干扰项——如果残留的是一个空格才会这样,但 >> 跳过前导空白,留下的必然是 \n

缓冲区逐步演示

步骤 操作 缓冲区剩余 变量值
1 cin >> a "\nhello\n" a = 42
2 getline(cin, s) "hello\n" s = "" ← 吃掉了空行
3 cout << "[" << s << "]" 输出 []

正确写法:先把残留的换行符吃掉

int a;
cin >> a;
cin.ignore(numeric_limits<streamsize>::max(), '\n');  // 跳过到行尾
string s;
getline(cin, s);
cout << "[" << s << "]";   // 输出 [hello]

需要 #include <limits>。简化写法(不考虑行内多余字符):

cin.ignore();   // 默认丢弃 1 个字符,够吃掉一个 '\n'

什么时候可以混用

写法 混用 getline 安全吗
cin >> n 之后 getline ❌ 留下 \n,读到空行
cin >> s(读单词)之后 getline ❌ 同样留下 \n
getline 之后 getline ✅ 完全安全,逐行读
cin.ignore() 清理之后再 getline ✅ 安全

考点总结(CSP-J 初赛选择题)

  1. cin >> 不消耗换行符,它读完目标数据就停,\n 留在缓冲区。
  2. getline 遇到 \n 就结束,读到空串也照样返回。
  3. 二者混用必须先 cin.ignore()(或 cin.get())清掉残留换行。
  4. 秒杀技巧:题目里 cin >> 后紧跟 getline优先怀疑输出是空串/缺一行,选项里找 [] 这类“空内容”答案。

思考题

cin >> a 改成 cin >> a >> ws;ws 操纵符),再 getline,输出是什么?

答案 [hello]ws(whitespace 操纵符)会连续跳过缓冲区中的所有空白字符(包括 \n),相当于轻量版的 ignore,之后的 getline 就能正常读到 hello