使用 ostream 格式化自定义类型
Format custom types with ostream
我们可以使用不同的选项更改流行为:
std::cout << 0xfabadau << '\n';
std::cout << std::hex << std::setfill('0') << std::setw(8) << 0xfabadau << '\n';
输出:
16431834
00fabada
现在假设我有一个 byte_buffer
自定义类型:
using byte = std::uint8_t;
using byte_buffer = std::vector<byte>;
std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
{
for (const auto &b : buffer) o << std::hex << int{b};
return o << std::dec;
}
使用它我无法应用自定义格式::
byte_buffer b { 0xfau, 0xbau, 0xdau, };
std::cout << b << '\n';
std::cout << std::hex << std::setfill('0') << std::setw(8) << b << '\n';
上面的代码显示了以下输出:
fabada
000000fabada
std::setfill
和 std::setw
在 之外 std::ostream &operator <<
正在影响 byte_buffer
的第一个 byte
在 内部 std::ostream &operator <<
因此观察到的输出,这不是我想要的,这不是我想要的。我想要的输出是:
fabada
00fabada
我应该如何更改 std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
以使 byte_buffer
以我想要的方式运行?
你可以像这样使用字节
std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
{
std::uint32_t temp=0;
for (const auto &b : buffer)
{
temp<<=8;
temp|=b;
}
return o << std::hex << temp << std::dec;
}
更灵活的方法
std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
{
std::ostringstream ss;
for (const auto &b : buffer)
{
ss<< std::hex << int{b};
}
return o << ss.str();
}
您始终可以获取标志并在您的函数中随意使用它们。例如(这里只处理宽度)
int width = o.width(), item_width;
int fill = o.fill();
if (width > 2*buffer.size())
item_width = width - 2*(buffer.size()-1);
else
item_width = 2;
for (const auto &b : buffer)
{
o << std::hex << std::setw(item_width) << setfill(fill) << int{b};
item_width = 2; fill = '0';
}
我们可以使用不同的选项更改流行为:
std::cout << 0xfabadau << '\n';
std::cout << std::hex << std::setfill('0') << std::setw(8) << 0xfabadau << '\n';
输出:
16431834 00fabada
现在假设我有一个 byte_buffer
自定义类型:
using byte = std::uint8_t;
using byte_buffer = std::vector<byte>;
std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
{
for (const auto &b : buffer) o << std::hex << int{b};
return o << std::dec;
}
使用它我无法应用自定义格式::
byte_buffer b { 0xfau, 0xbau, 0xdau, };
std::cout << b << '\n';
std::cout << std::hex << std::setfill('0') << std::setw(8) << b << '\n';
上面的代码显示了以下输出:
fabada 000000fabada
std::setfill
和 std::setw
在 之外 std::ostream &operator <<
正在影响 byte_buffer
的第一个 byte
在 内部 std::ostream &operator <<
因此观察到的输出,这不是我想要的,这不是我想要的。我想要的输出是:
fabada 00fabada
我应该如何更改 std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
以使 byte_buffer
以我想要的方式运行?
你可以像这样使用字节
std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
{
std::uint32_t temp=0;
for (const auto &b : buffer)
{
temp<<=8;
temp|=b;
}
return o << std::hex << temp << std::dec;
}
更灵活的方法
std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer)
{
std::ostringstream ss;
for (const auto &b : buffer)
{
ss<< std::hex << int{b};
}
return o << ss.str();
}
您始终可以获取标志并在您的函数中随意使用它们。例如(这里只处理宽度)
int width = o.width(), item_width;
int fill = o.fill();
if (width > 2*buffer.size())
item_width = width - 2*(buffer.size()-1);
else
item_width = 2;
for (const auto &b : buffer)
{
o << std::hex << std::setw(item_width) << setfill(fill) << int{b};
item_width = 2; fill = '0';
}