本节将详细探讨 <iostream> 输出类 ostream 的各项功能。
插入运算符(<<)
插入运算符(<<)用于向输出流写入数据。C++ 对所有内置类型均已预定义插入操作,也允许为自定义类重载该运算符。
在前面的课程中,你已看到 istream 与 ostream 均派生自 ios。ios(以及 ios_base)的职责之一便是控制输出的格式选项。
格式设置
修改格式有两种途径:标志位(flags) 与 操控符(manipulators)。
- 标志位可视为布尔开关,通过
setf()/unsetf()进行开/关。 - 操控符是插入流中的对象,用于影响输入/输出的格式。
示例:默认情况下,正数前不输出 + 号;使用 std::ios::showpos 可改变此行为:
std::cout.setf(std::ios::showpos); // 打开 showpos 标志
std::cout << 27 << '\n'; // 输出 +27
可用按位或(|)同时打开多个标志:
std::cout.setf(std::ios::showpos | std::ios::uppercase);
std::cout << 1234567.89f << '\n'; // 输出 +1.23457E+06
关闭标志使用 unsetf():
std::cout.setf(std::ios::showpos);
std::cout << 27 << '\n';
std::cout.unsetf(std::ios::showpos);
std::cout << 28 << '\n';
// 输出:
// +27
// 28
格式组(format groups)的注意事项
某些标志属于同一格式组,彼此互斥。例如,basefield 组包含 dec、hex、oct,默认启用 dec:
std::cout.setf(std::ios::hex); // 仅打开 hex,但未关闭 dec
std::cout << 27 << '\n'; // 仍输出 27(未生效)
解决方法:
- 手动关闭冲突标志:
std::cout.unsetf(std::ios::dec);
std::cout.setf(std::ios::hex);
std::cout << 27 << '\n'; // 输出 1b
- 使用双参数
setf():传入欲设置标志及其所属格式组,组内其他标志自动关闭:
std::cout.setf(std::ios::hex, std::ios::basefield);
std::cout << 27 << '\n'; // 输出 1b
操控符(manipulators)
使用操控符通常比手动开关标志更方便。例如:
std::cout << std::hex << 27 << '\n'; // 十六进制输出
std::cout << 28 << '\n'; // 仍在十六进制
std::cout << std::dec << 29 << '\n'; // 恢复十进制
// 输出:
// 1b
// 1c
// 29
常用格式控制一览
下表列出常用标志、操控符及成员函数。标志位于 std::ios;操控符位于 std 命名空间;成员函数位于 std::ostream。
| 分组 | 标志 | 含义 |
|---|---|---|
| — | std::ios::boolalpha | 布尔值输出 true/false;否则输出 0/1 |
| 操控符 | 含义 | |
| — | — | |
std::boolalpha / std::noboolalpha | 切换布尔文本/数字输出 |
示例:
std::cout << true << ' ' << false << '\n'; // 1 0
std::cout.setf(std::ios::boolalpha);
std::cout << true << ' ' << false << '\n'; // true false
std::cout << std::noboolalpha << true << ' ' << false << '\n'; // 1 0
| 分组 | 标志 | 含义 |
|---|---|---|
| — | std::ios::showpos | 正数前显示 + |
| 操控符 | 含义 | |
| — | — | |
std::showpos / std::noshowpos | 切换正数前是否显示 + |
示例:
std::cout << 5 << '\n'; // 5
std::cout.setf(std::ios::showpos);
std::cout << 5 << '\n'; // +5
std::cout << std::noshowpos << 5 << '\n'; // 5
| 分组 | 标志 | 含义 |
|---|---|---|
| — | std::ios::uppercase | 十六进制/科学计数法使用大写字母 |
| 操控符 | 含义 | |
| — | — | |
std::uppercase / std::nouppercase | 切换大小写 |
示例:
std::cout << 12345678.9 << '\n'; // 1.23457e+007
std::cout.setf(std::ios::uppercase);
std::cout << 12345678.9 << '\n'; // 1.23457E+007
| 分组 | 标志 | 含义 |
|---|---|---|
std::ios::basefield | std::ios::dec | 十进制(默认) |
std::ios::hex | 十六进制 | |
std::ios::oct | 八进制 | |
| 操控符 | 含义 | |
| — | — | |
std::dec / std::hex / std::oct | 切换进制 |
示例:
std::cout << 27 << '\n'; // 27
std::cout << std::hex << 27 << '\n'; // 1b
std::cout << std::oct << 27 << '\n'; // 33
精度、计数法与小数点
通过操控符或标志可控制浮点数的显示精度与格式。
| 分组 | 标志 | 含义 |
|---|---|---|
std::ios::floatfield | std::ios::fixed | 定点表示 |
std::ios::scientific | 科学计数法 | |
std::ios::showpoint | 始终显示小数点及尾随零 | |
| 操控符 | 含义 | |
| — | — | |
std::fixed / std::scientific | 切换定点/科学计数法 | |
std::showpoint / std::noshowpoint | 切换是否强制显示小数点 | |
std::setprecision(int) | 设置浮点精度(位于 <iomanip>) |
示例:
std::cout << std::fixed << std::setprecision(3) << 123.456 << '\n'; // 123.456
std::cout << std::scientific << std::setprecision(3) << 123.456 << '\n'; // 1.235e+002
若未指定 fixed/scientific,精度指有效数字位数:
std::cout << std::setprecision(3) << 123.456 << '\n'; // 123
使用 showpoint 强制显示小数点:
std::cout << std::showpoint << std::setprecision(3) << 123.456 << '\n'; // 123.
宽度、填充字符与对齐
默认输出时数字周围不留空格。可通过设置字段宽度并指定对齐方式实现左/右/内部对齐。
| 分组 | 标志 | 含义 |
|---|---|---|
std::ios::adjustfield | std::ios::internal | 符号左对齐,数值右对齐 |
std::ios::left | 整体左对齐 | |
std::ios::right | 整体右对齐(默认) | |
| 操控符 | 含义 | |
| — | — | |
std::internal / std::left / std::right | 切换对齐方式 | |
std::setfill(char) | 设置填充字符(位于 <iomanip>) | |
std::setw(int) | 设置字段宽度(位于 <iomanip>) |
示例:
std::cout << std::setw(10) << -12345 << '\n'; // 默认右对齐
std::cout << std::setw(10) << std::left << -12345 << '\n'; // 左对齐
std::cout << std::setw(10) << std::internal << -12345 << '\n'; // 内部对齐
输出:
-12345
-12345
- 12345
注意:setw() 与 width() 仅影响下一次输出,不具持久性。
设置填充字符:
std::cout.fill('*');
std::cout << std::setw(10) << std::left << -12345 << '\n'; // -12345****
ostream 及整个 <iostream> 库还包含更多输出函数、标志与操控符,视需求可进一步查阅标准库文档。
