标准 IO 流
定义与作用
标准 IO 流提供控制台输入输出的抽象层。四个预定义流对象连接标准输入输出通道:
std::cin >> x; // 标准输入 (stdin)
std::cout << x; // 标准输出 (stdout,缓冲)
std::cerr << x; // 标准错误 (stderr,无缓冲)
std::clog << x; // 标准日志 (stderr,缓冲)
核心原理
流继承体系
流状态位
完整示例
示例一:飞翔科技运维监控面板输入
场景说明:李眉编写一个交互式终端程序,演示 cin 安全读取和流状态管理。
#include <iostream>
#include <limits>
#include <string>
#include <iomanip>
void clearInputBuffer() {
std::cin.clear(); // 清除错误标志
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
int main() {
std::cout << "=== 飞翔科技运维监控面板 ===\n\n";
// 1. 基本输入 —— 使用 while(cin) 循环
std::cout << "请输入多条服务器地址 (输入空行结束):\n";
std::string server;
int count = 0;
while (std::getline(std::cin, server) && !server.empty()) {
std::cout << " [" << ++count << "] 已添加: " << server << "\n";
}
std::cout << "共录入 " << count << " 台服务器\n\n";
// 2. 错误处理 —— 输入非数字时恢复
int threshold;
while (true) {
std::cout << "输入告警阈值 (整数): ";
if (std::cin >> threshold) {
std::cout << "阈值已设置: " << threshold << "%\n";
break;
}
std::cerr << "[错误] 请输入有效的整数!\n";
clearInputBuffer();
}
// 3. 混合输入 —— 数字和字符串交替
clearInputBuffer(); // 清除 >> 后残留的换行
std::cout << "\n输入监控项 (格式: 名称 CPU占比):\n";
std::string itemName;
double cpuUsage;
std::cout << "> ";
std::cin >> itemName >> cpuUsage;
std::cout << "监控项: " << itemName << " CPU=" << cpuUsage << "%\n";
// 4. cerr vs clog
std::cerr << "[cerr] 立即输出(无缓冲)—— 紧急告警!\n";
std::clog << "[clog] 缓冲输出 —— 常规日志\n";
std::cout << "--- 日志分隔线 ---\n";
// 5. 检查流状态
std::cout << "\n流状态检查:\n";
std::cout << " cin.good(): " << std::cin.good() << "\n";
std::cout << " cin.eof(): " << std::cin.eof() << "\n";
std::cout << " cin.fail(): " << std::cin.fail() << "\n";
}
预期输出(示例交互):
=== 飞翔科技运维监控面板 ===
请输入多条服务器地址 (输入空行结束):
192.168.1.101
[1] 已添加: 192.168.1.101
192.168.1.102
[2] 已添加: 192.168.1.102
共录入 2 台服务器
输入告警阈值 (整数): 八十五
[错误] 请输入有效的整数!
输入告警阈值 (整数): 85
阈值已设置: 85%
输入监控项 (格式: 名称 CPU占比):
> web-server-01 62.5
监控项: web-server-01 CPU=62.5%
[cerr] 立即输出(无缓冲)—— 紧急告警!
[clog] 缓冲输出 —— 常规日志
--- 日志分隔线 ---
流状态检查:
cin.good(): 1
cin.eof(): 0
cin.fail(): 0
逐段分析:
std::getline(cin, s)读取整行,适合含空格的输入cin.clear()清除错误标志后cin才能继续使用cin.ignore(...)丢弃缓冲区残留,避免混合>>和getline时的问题cerr无缓冲,适合紧急告警;clog有缓冲,适合日志记录- 流支持隐式转为
bool:if (cin)等价于if (!cin.fail())
示例二:sync_with_stdio 性能对比
场景说明:白歌测试 sync_with_stdio 对大数据量 IO 的性能影响。
#include <iostream>
#include <chrono>
#include <cstdio>
int main() {
const int N = 1'000'000;
// 测试1:默认(与 C stdio 同步)
auto start1 = std::chrono::steady_clock::now();
for (int i = 0; i < N; ++i)
std::cout << i << '\n';
auto end1 = std::chrono::steady_clock::now();
auto t1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start1);
// 测试2:关闭同步
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); // 解除 cin 和 cout 的绑定
auto start2 = std::chrono::steady_clock::now();
for (int i = 0; i < N; ++i)
std::cout << i << '\n';
auto end2 = std::chrono::steady_clock::now();
auto t2 = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - start2);
// 恢复同步
std::ios::sync_with_stdio(true);
std::cout << "\n=== 飞翔科技 IO 性能测试 ===\n";
std::cout << "输出 " << N << " 个整数:\n";
std::cout << " 同步开启: " << t1.count() << " ms\n";
std::cout << " 同步关闭: " << t2.count() << " ms\n";
std::cout << " 加速比: " << std::fixed << std::setprecision(1)
<< (double)t1.count() / t2.count() << "x\n";
std::cout << "\n注意: 关闭同步后不能混用 C++ cout 和 C printf/scanf\n";
}
预期输出(数值因环境而异):
(输出一百万行整数...)
=== 飞翔科技 IO 性能测试 ===
输出 1000000 个整数:
同步开启: 3421 ms
同步关闭: 1287 ms
加速比: 2.7x
注意: 关闭同步后不能混用 C++ cout 和 C printf/scanf
逐段分析:
sync_with_stdio(false)关闭 C++ 流与 C stdio 的内部同步,大幅提升性能- 关闭后 C++ 流使用独立缓冲区,不能与
printf/scanf混用 cin.tie(nullptr)解绑cin和cout,避免每次输入前自动刷新输出缓冲- 建议在
main函数开始时调用,且之后不能再改回
易错场景与面试考点
易错场景
1. >> 后残留换行导致 getline 行为异常
int age;
std::cin >> age; // 输入 "25\n"
std::string name;
std::getline(std::cin, name); // 直接读取到残留的 "\n",name 为空!
// 解决:cin.ignore() 清除换行
2. cerr 和 clog 输出可能交叉
// 由于缓冲策略不同,cerr 和 clog 的输出顺序可能不如预期
std::clog << "A";
std::cerr << "B";
std::clog << "C"; // "BAC" 还是 "ABC" 不确定
3. cin 失败后不清理状态
int x;
while (!(std::cin >> x)) {
// ❌ 如果没有 cin.clear() + ignore(),cin 永远失败
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
面试考点
| 考点 | 要点 |
|---|---|
| 四标准流 | cin/stdin, cout/stdout(缓冲), cerr/stderr(无缓冲), clog/stderr(缓冲) |
| 流状态位 | goodbit/eofbit/failbit/badbit,组合使用 |
| operator bool | while(cin >> x) 检测 fail(),EOF 时也退出 |
| sync_with_stdio | 默认与 C stdio 同步,关闭可提速 2-10 倍 |
| cin.tie | cin 默认绑定 cout,每次读取前刷新 cout |
| getline vs >> | getline 读行含空格,>> 按空白字符分割 |
| 错误恢复 | clear() + ignore() 是标准恢复模式 |