cin 与 cout:iostream 输入输出
更新时间:2026-08-27。本文是
languages/cpp/主题入门层第 1 篇。上一篇用std::cout打出了 Hello,这一篇把 C++ 的输入输出讲透:cin/cout怎么用、和 C 的printf/scanf比好在哪、以及新手最容易踩的输入缓冲区的坑。
本文要回答的问题
cin/cout的基本用法和组合技?- 和
printf/scanf相比,流式 IO 到底好在哪、又有啥代价? - 为什么
cin >> n之后再用getline会"跳过去"?
一、cin 与 cout 基本用法
cin 是 std::cin——标准输入流,配合 >>(流提取运算符)读数据;cout 配 << 输出。两个运算符方向相反,很好记:>> 指向变量(数据进来),<< 指向屏幕(数据出去)。
#include <iostream>
#include <string>
int main() {
std::string name;
int age = 0;
std::cout << "请输入姓名和年龄:";
std::cin >> name >> age; // 一次读两个,空格分隔
std::cout << "你好," << name << ",你 " << age << " 岁了" << std::endl;
return 0;
}std::cin >> name >> age 会跳过空白(空格、Tab、换行)依次读入:先读一个字符串到 name,再读一个整数到 age。运行时输入 张三 25,程序就能正确拆开。
二、和 printf / scanf 对比:省心但要注意类型
| 对比项 | printf / scanf(C) | cin / cout(C++) |
|---|---|---|
| 格式 | 要写 %d %s 等占位符 | 自动识别类型,<< 直接塞 |
| 类型安全 | 写错 %d 传 double 是未定义行为 | 编译期检查,类型不匹配报错 |
| 可读性 | 长格式串难维护 | 链式清晰 |
| 性能 | 快(格式化一次性解析) | 略慢(默认和 C 流同步) |
cin / cout 默认和 C 的 stdio 是同步的(保证 printf 和 cout 混用不乱序),这带来了额外开销。如果你确定整个程序只用 C++ 流,可以在 main 开头关掉同步提速:
#include <iostream>
int main() {
std::ios::sync_with_stdio(false); // 不再和 stdio 同步,提速
std::cin.tie(nullptr); // 不再每次输入前刷新 cout
// ... 正常读写
}竞赛题和 IO 密集型程序常这么写,性能可以接近 scanf。原理是关掉同步后 cin/cout 直接用内部缓冲,少了层层转发。不过要先想清楚:一旦关了同步,就别再混用 printf 和 cout,否则输出顺序可能乱。
三、读整行:getline
>> 读到空白就停,想读"一整行含空格"要用 std::getline:
#include <iostream>
#include <string>
int main() {
std::string line;
std::getline(std::cin, line); // 读一整行,含空格
std::cout << "你输入了:" << line << std::endl;
return 0;
}四、新手最常踩的坑:cin 之后 getline 被"跳过"
这是 cin / getline 混用时的经典 bug。看这个:
int n;
std::string line;
std::cin >> n; // 输入 5 后回车
std::getline(std::cin, line); // 结果 line 是空的!原因:>> 读到 5 就停,换行符 \n 还留在缓冲区;接着 getline 读到这个残留的 \n,以为整行已经结束,直接返回空行。
解决办法:在 >> 之后把残留的换行吃掉:
std::cin >> n;
std::cin.ignore(); // 丢弃缓冲区里一个字符(那个 \n)
std::getline(std::cin, line); // 这次能正常读到std::cin.ignore() 默认丢弃一个字符。如果担心前面残留多个字符(比如输入了 abc\n),可以 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')——读到换行为止,把整行坏输入清掉。这和 C 里 while (getchar() != '\n') 的思路一模一样,只是 C++ 封装成了函数。
五、怎么判断输入是否成功
scanf 看返回值,cin 也一样:
int n;
if (std::cin >> n) {
// 成功读到一个整数
} else {
// 失败:可能是文件结束,也可能是输入了非数字
}>> 失败时会置 cin 的失败标志,后续读取都会直接失败。需要继续读时先清除标志:
std::cin.clear(); // 清除错误标志
std::cin.ignore(); // 丢掉坏输入入门阶段记住这个模式就行:读前先判断,失败要 clear + ignore。综合练习篇学生成绩系统会用到。
六、格式化输出:setw / setprecision
printf 的 %5d、%.2f 在 C++ 里对应流操纵符(<iomanip>):
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.1415926;
std::cout << std::fixed << std::setprecision(2) << pi << std::endl; // 3.14
std::cout << std::setw(6) << 42 << std::endl; // " 42" 右对齐占6位
return 0;
}| C 写法 | C++ 写法 | 效果 |
|---|---|---|
%5d | std::setw(5) | 宽度 5,右对齐 |
%.2f | std::fixed << std::setprecision(2) | 保留 2 位小数 |
%x | std::hex | 十六进制 |
注意 setw 只对下一次输出有效,setprecision 会一直生效——这和 C 的一次性占位符行为不一样,容易记混。
七、与本站主线衔接
- 流式 IO 的底层缓冲与性能,见高手层流式 IO 深挖;
sync_with_stdio关同步的底层机制(C 流与 C++ 流如何桥接),与L3 内存与 IO相关;- C 的输入输出对照,见C 语言 scanf 输入与 printf 格式化输出。
一句话总结
cin / cout 用 >> / << 自动识别类型,比 printf / scanf 省心且类型安全,代价是默认与 stdio 同步带来的性能开销(可关同步提速);最大的坑是 >> 之后缓冲区残留换行导致 getline 读到空行,用 cin.ignore() 吃掉就好。
上一篇:环境搭建与第一个程序 下一篇:命名空间与 using