如何让我的十六进制字符串在 C++ 中包含中间零?

问题描述 投票:0回答:1

我正在尝试将存储为字节向量的 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

我显然在这里做错了什么。我尝试过刷新缓冲区并在事后插入破折号,但仍然没有成功。

c++ c++17 uuid iostream iomanip
1个回答
0
投票

正如评论中所解释的,

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
© www.soinside.com 2019 - 2024. All rights reserved.