本节将详细探讨 <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>
库还包含更多输出函数、标志与操控符,视需求可进一步查阅标准库文档。