我正在尝试将存储为字节向量的 UUID 输出为带破折号的十六进制字符串。当任何单个字节有前导零时,我的输出字符串会跳过它。我正在使用 std::setw(2) 并且仍然出现这种行为。
我尝试了以下代码:
#include <iomanip>
#include <iostream>
std::ostream& operator<<(std::ostream &os, const Id &id) {
std::ios oldState(nullptr);
oldState.copyfmt(os);
os << std::hex << std::uppercase << std::setfill('0') << std::setw(2);
for (int i = 0; i < 16; i++) {
os << (int)id.id_[i];
if (i == 3 || i == 5 || i == 7 || i == 9) os << '-';
}
os.copyfmt(oldState);
return os;
}
我的预期输出是这样的:
01020304-0102-0304-0506-AA0F0E0D0C0B
我得到的是:
1234-12-34-56-AAFEDCB
我显然在这里做错了什么。我尝试过刷新缓冲区并在事后插入破折号,但仍然没有成功。
正如评论中所解释的,
std::setw
是一次性操纵者。它仅适用于下一个输出项。之后,流宽度重置为 0。
解决方法很简单:将
setw
移至循环中。
出于演示目的,我创建了
struct Id
。
// main.cpp
#include <iomanip>
#include <iostream>
#include <vector>
#include <initializer_list>
struct Id
{
Id(std::initializer_list<short> l)
: id_{ l }
{}
std::vector<short> id_;
};
std::ostream& operator<<(std::ostream& os, const Id& id) {
std::ios oldState(nullptr);
oldState.copyfmt(os);
os << std::hex << std::uppercase << std::setfill('0');
for (int i = 0; i < 16; i++) {
os << std::setw(2) << (int)id.id_[i];
if (i == 3 || i == 5 || i == 7 || i == 9) os << '-';
}
os.copyfmt(oldState);
return os;
}
int main()
{
Id id{ 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xAA, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B };
std::cout << id << '\n';
return 0;
}
输出:
01020304-0102-0304-0506-AA0F0E0D0C0B