输入输出与格式化:cin、cout、endl、setw、setprecision
说实话,C++的输入输出这块,看着简单,但坑不少。我刚开始学的时候,觉得不就是个打印东西嘛,有啥好学的?结果后来写项目时,被格式化输出折腾得够呛。今天咱们就把这几个家伙——cin、cout、endl、setw、setprecision——彻底聊透。
1. cout:最常用的“嘴”
cout 说白了就是 C++ 的“标准输出流”。你用它把数据打印到屏幕上。我个人习惯把它想象成一根管子,数据从程序里流到屏幕上。
#include <iostream>
using namespace std;
int main() {
cout << "Hello, 世界!" << endl;
cout << 42 << endl;
cout << 3.14159 << endl;
return 0;
}
你看,字符串、整数、浮点数,一股脑儿往 cout 后面塞就行。它自己知道怎么处理。
<< 连起来写。比如 cout << "a=" << a << ", b=" << b << endl;。这样代码更紧凑。
2. cin:程序的眼睛和耳朵
cin 是标准输入流。它从键盘读取数据,然后存到变量里。我在项目中遇到过一个问题:用户输入时不小心多打了个空格,结果程序就乱了。嗯,这里要注意 cin 默认以空格、换行符作为分隔符。
int age;
string name;
cout << "请输入你的名字和年龄:";
cin >> name >> age;
cout << "你好," << name << ",你" << age << "岁了。" << endl;
你想想看,如果用户输入“张三 25”,程序就能正确读取。但如果用户输入“张三 李四 25”,那 name 会拿到“张三”,age 会尝试把“李四”转成整数——然后就崩了。
cin 读取用户输入的路径,结果路径里带空格,程序直接崩溃。后来改用 getline() 才解决。记住:cin >> 遇到空格就停,getline() 才能读整行。
3. endl:不只是换行
endl 有两个作用:一是换行,二是刷新输出缓冲区。说白了,它把数据从内存“推”到屏幕上。我刚开始觉得 endl 和 "\n" 没区别,直到有一次写日志程序,发现 endl 会导致频繁刷新,性能下降不少。
// 这两种写法效果差不多,但底层机制不同
cout << "第一行" << endl;
cout << "第二行" << "\n";
"\n" 就行,性能更好。需要立即显示内容时(比如日志、调试信息),用 endl 强制刷新缓冲区。
4. setw:对齐强迫症患者的福音
setw 设置下一个输出项的宽度。说白了,就是让数据“站好队”。我在做报表程序时,没有 setw 简直没法活。
#include <iomanip>
int main() {
cout << setw(10) << "姓名" << setw(10) << "年龄" << endl;
cout << setw(10) << "张三" << setw(10) << 25 << endl;
cout << setw(10) << "李四" << setw(10) << 30 << endl;
return 0;
}
输出效果:
姓名 年龄
张三 25
李四 30
注意:setw 只对紧接着的一个输出项有效。每次都要重新设置。我刚开始老忘记这一点,结果后面的数据全乱了。
5. setprecision:控制小数位数
setprecision 设置浮点数的小数精度。默认情况下,它控制有效数字的位数。配合 fixed 使用,就能控制小数点后的位数。
double pi = 3.141592653589793;
cout << "默认:" << pi << endl;
cout << setprecision(3) << "3位有效数字:" << pi << endl;
cout << fixed << setprecision(2) << "2位小数:" << pi << endl;
输出:
默认:3.14159
3位有效数字:3.14
2位小数:3.14
fixed 和 setprecision 是“粘性”的,设置一次后一直有效,直到被修改。而 setw 是“一次性”的,每次都要重新设置。
6. 综合示例:做一个简单的成绩单
咱们把上面这些知识点串起来,写一个成绩单程序。你想想看,如果不用格式化,打印出来的成绩单歪歪扭扭的,多难看。
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main() {
string name1 = "张三", name2 = "李四", name3 = "王五";
double score1 = 95.5, score2 = 88.0, score3 = 72.3;
cout << left << setw(12) << "姓名"
<< right << setw(10) << "成绩" << endl;
cout << string(22, '-') << endl;
cout << left << setw(12) << name1
<< right << setw(10) << fixed << setprecision(1) << score1 << endl;
cout << left << setw(12) << name2
<< right << setw(10) << score2 << endl;
cout << left << setw(12) << name3
<< right << setw(10) << score3 << endl;
return 0;
}
输出效果:
姓名 成绩
--------------------
张三 95.5
李四 88.0
王五 72.3
你看,left 和 right 控制对齐方向,setw 控制宽度,fixed 和 setprecision 控制小数位数。这样打印出来的表格,是不是清爽多了?
7. 知识体系总览
下面这张图,把本章的核心知识点串起来了。我建议你多看几遍,理解每个组件之间的关系。
8. 避坑总结
最后,我把自己踩过的坑整理一下,你写代码时多留个心眼:
- cin 遇到空格就停:读取带空格的字符串,用
getline(cin, str)。 - endl 会刷新缓冲区:频繁打印时用
"\n"代替,性能更好。 - setw 只对下一个有效:每个输出项前都要重新设置。
- setprecision 默认是有效数字:配合
fixed才是小数点后位数。 - 头文件别忘:
setw和setprecision需要#include <iomanip>。
好了,输入输出这块就聊到这儿。你把这些代码自己敲一遍,跑一跑,比光看强十倍。下次咱们再聊点别的。