第11.12.2章: 完整的 <iomanip> 参考
<iomanip> 头文件提供带参数的操纵器。这些操纵器会修改流的内部状态,而该状态会一直保留到你显式修改为止。这是根本性的设计缺陷 — 见第11.12章中“为什么 C++ iostream 有根本性缺陷”。fast_io 的操纵器是无状态的,不会遇到这些问题。
字段宽度与填充
| 操纵器 | 说明 | 示例 |
|---|---|---|
std::setw(n) |
把最小字段宽度设为 n 个字符 |
std::cout << std::setw(10) << 42; |
把填充字符设为 c |
Set fill character to c |
std::cout << std::setfill('0') << std::setw(5) << 42; |
警告:std::setw 只作用于下一次输出操作,之后重置为 0。这不一致,而且容易出错。
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::setw(10) << 42 << '\n'; // 42
std::cout << 42 << '\n'; // 42 (width reset!)
std::cout << std::setfill('0') << std::setw(5) << 42 << '\n'; // 00042
return 0;
}
数制
| 操纵器 | 说明 | 示例 |
|---|---|---|
std::setbase(n) |
把数制设为 n(8、10 或 16) |
std::cout << std::setbase(16) << 255; (prints ff) |
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::setbase(16) << 255 << '\n'; // ff
std::cout << std::setbase(8) << 255 << '\n'; // 377
std::cout << std::setbase(10) << 255 << '\n'; // 255
return 0;
}
精度
| 操纵器 | 说明 | 示例 |
|---|---|---|
std::setprecision(n) |
把浮点精度设为 n 位 |
std::cout << std::setprecision(3) << 3.14159; (prints 3.14) |
注意:精度会一直保留到被修改为止。与 std::fixed 或 std::scientific 配合时,它控制小数位数。
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.14159;
std::cout << std::setprecision(3) << pi << '\n'; // 3.14
std::cout << pi << '\n'; // 3.14 (precision persists!)
std::cout << std::fixed << std::setprecision(2) << pi << '\n'; // 3.14
std::cout << std::scientific << std::setprecision(4) << pi << '\n'; // 3.1416e+00
return 0;
}
其他操纵器
| 操纵器 | 说明 |
|---|---|
std::resetiosflags(f) |
清除指定的格式标志 |
std::setiosflags(f) |
设置指定的格式标志 |
格式标志包括:std::ios::left、std::ios::right、std::ios::internal、std::ios::dec、std::ios::hex、std::ios::oct、std::ios::fixed、std::ios::scientific、std::ios::boolalpha、std::ios::showbase、std::ios::showpoint、std::ios::showpos、std::ios::skipws、std::ios::uppercase、std::ios::unitbuf。
#include <iostream>
#include <iomanip>
int main() {
// Set flags
std::cout << std::setiosflags(std::ios::hex | std::ios::showbase);
std::cout << 255 << '\n'; // 0xff
// Reset flags
std::cout << std::resetiosflags(std::ios::hex);
std::cout << std::setiosflags(std::ios::dec);
std::cout << 255 << '\n'; // 255
return 0;
}
为什么这很糟糕
所有这些操纵器都会修改流的内部状态。看看这个:
#include <iostream>
#include <iomanip>
void print_hex(int value) {
std::cout << std::hex << value << '\n';
// Stream is now in hex mode!
}
int main() {
print_hex(255); // Prints "ff"
std::cout << 255 << '\n'; // Also prints "ff"!
// Must manually restore: std::cout << std::dec;
}
这是维护噩梦。你必须在每次使用后记得恢复流状态,否则后续代码会表现异常。异常可能把流留在不一致的状态。多个线程可能互相破坏对方的格式化。
fast_io 的操纵器无状态:
#include <fast_io.h>
void print_hex(int value) {
using namespace ::fast_io::iomnp;
println(::fast_io::mnp::hex(value));
// No state to restore!
}
int main() {
using namespace ::fast_io::iomnp;
print_hex(255); // Prints "ff"
println(255); // Prints "255" (decimal, as expected)
}
每个操纵器只作用于它包住的那个值。没有会被破坏的全局状态。