附:cout 的格式控制

setw / setfill / fixed / setprecision / oct…一页看懂怎么对齐、定宽、留几位小数、换进制。

GESPCSP-J

◎学完你会

0前提:操纵符从哪来

格式控制靠 操纵符(manipulator)——它们被 << 夹在中间,临时改 cout 的输出状态。

#include <iostream> #include <iomanip> // setw / setfill / setprecision / fixed / oct…都在这 using namespace std;

想用上面的命令,第一行必须加 #include <iomanip>,否则编译不过。先记一张速查表:

需求核心命令(<iomanip>)一句话
固定宽度setw(n)只对下一个输出项生效,之后自动恢复
填充字符setfill(c)宽度不够时用什么填,默认空格
对齐方式left / right / internal左 / 右(默认)/ 内对齐(符号位)
浮点精度setprecision(n)、fixed、scientific有效数字 or 小数位数 / 定点 / 科学计数
进制oct / hex / showbase / uppercase八 / 十六进制、带前缀、大写 A-F
布尔 / 正号boolalpha / showpos输出 true/false、正数带 +

1实验:格式控制台

调一个参数,下面这行代码和输出格子立刻变。看清 setw 补了几位、setfill 用什么补、三种对齐怎么摆。

2浮点精度:3 种模式别搞混

同一个 setprecision(n),在三种模式下含义完全不同。

模式n 的含义3.1415926535
setprecision(3)(默认)保留 3 位有效数字3.14
fixed << setprecision(2)保留 2 位小数(定点)3.14
scientific << setprecision(4)科学计数法、4 位小数3.1416e+00

点"单步"看这行代码在 fixed 之后怎么一步步被"锁死"。

// 默认模式:n = 有效数字位数 cout << setprecision(3) << pi << endl; // fixed 之后:n = 小数点后位数(且一直延续) cout << fixed << setprecision(2) << pi << endl; cout << setprecision(6) << pi << endl; cout << scientific << setprecision(4) << pi << endl;
初始
3.1415926535
点"单步"开始:看 fixed 是怎么把输出"锁"成定点小数、并一路延续下去的。

3进制 · 布尔 · 正号:一组小开关

要的效果代码实测输出
八进制、带前缀 0oct << showbase << 2550377
十六进制、大写 + 前缀hex << uppercase << 2550XFF
十六进制默认(小写!)hex << 255ff
布尔输出成 true / falseboolalpha << truetrue
正数带 + 号showpos << 123 << " " << -456+123 -456

反着关:noshowbase、noboolalpha、noshowpos 恢复默认。

4实战:一行一行拼表格

表头 + 分隔线 + 数据行。要点:left 只设一次、每个字段都要 setw、小数用 fixed << setprecision(2)。

cout << left << setw(12) << "Name" << setw(10) << "Price" << setw(6) << "Qty" << endl; cout << setfill('-') << setw(28) << "" << setfill(' ') << endl; cout << setw(12) << "Apple" << fixed << setprecision(2) << setw(10) << 5.99 << setw(6) << 10 << endl; cout << setw(12) << "Banana" << setw(10) << 3.50 << setw(6) << 20 << endl;
Name Price Qty ---------------------------- Apple 5.99 10 Banana 3.50 20

顺带记一下:endl = 换行 + 刷新缓冲区;flush 只刷新不换行;ends 输出空字符 \0(少用)。

!易错点

坑 1:setw 只管下一个输出项。 连排多个字段,每个都要写 setw。实测 setw(8)<<"ab"<<"cd" 输出 [ab cd]——只有 ab 被补宽。
坑 2:中文 + setw 一定错位。 setw 按 UTF-8 字节计宽(一汉字 3 字节),不按显示列。实测 setfill('-')<<setw(8)<<"姓名" 只补 2 个短横 --姓名,不是 6 个。要对齐中文,别用 setw。
坑 3:fixed / scientific 会"锁死"精度并一路延续。 fixed 之后 setprecision(6) 是 6 位小数、不是 6 位有效数字。复原要用 cout.unsetf(ios::fixed | ios::scientific)。
坑 4:多数状态会延续。 left/right、setfill、showbase、boolalpha、showpos 一旦设置,后面的输出全受影响。用完记得复原:right、setfill(' ')、noshowbase、noboolalpha、noshowpos。

✎练一练

1. 想用 setw、setfill、fixed、setprecision 这些格式控制命令,必须先包含哪个头文件?
解析:选 B。这些操纵符都声明在 <iomanip> 里;<iostream> 只提供最基本的 cin/cout。
2. 执行 cout << setfill('*') << setw(6) << "ab";,输出是什么?(默认右对齐)
解析:选 C。setw(6) 把 "ab" 补到 6 位,右对齐所以 4 个 * 在左边,得 ****ab。
3. 想把 "abc" 靠左、右边用 = 补满到 10 位,正确写法是?
解析:选 A。靠左用 left,填充在内容右侧,得 abc=======。默认是右对齐(C 会是右边靠左、左边填 =)。
4. 想把 3.1415926 四舍五入输出成 3.142(保留 3 位小数),应写?
解析:选 D。要"3 位小数"必须 fixed 配合 setprecision(3);光 setprecision(3) 是 3 位有效数字,会输出 3.14。
5. 读程序:输出是什么?
int x = 255;
cout << setfill('0') << setw(6) << hex << x << " " << fixed << setprecision(2) << 3.1415926;
解析:选 B。255 的十六进制默认是小写 ff(没加 uppercase);setfill('0')<<setw(6) 补成 0000ff;后面 fixed<<setprecision(2) 只作用于浮点数,3.1415926 → 3.14。

✦跨学科:信息排版(版式设计)

格式控制就是一门"等宽排版"。等宽字体里 1 个英文字符占 1 列、1 个汉字占 2 列,终端靠"列"对齐——setw 却是按"字符/字节"计数,一个汉字在 UTF-8 下占 3 字节、显示只占 2 列。于是 setw(9) 对齐"数学"(2 汉字 = 6 字节)只补 3 个空格,显示却是 4 列汉字 + 3 空格 = 7 列,离期望的 9 列差 2 列。

可感的数字就在上面:期望 9 列,实际 7 列,错位 2 列。排版工具都要分清"字节 / 字符 / 显示宽度"是三回事。