如何使用 ostream 在 C++ 中将无符号字符打印为十六进制?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/673240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:39:23  来源:igfitidea点击:

how do I print an unsigned char as hex in c++ using ostream?

c++formattingostream

提问by Nathan Fellman

I want to work with unsigned 8-bit variables in C++. Either unsigned charor uint8_tdo the trick as far as the arithmetic is concerned (which is expected, since AFAIK uint8_tis just an alias for unsigned char, or so the debugger presents it.

我想在 C++ 中使用无符号 8 位变量。无论是unsigned charuint8_t做的伎俩,只要算术而言(这是意料之中的,因为据我所知uint8_t仅仅是一个别名unsigned char,还是让调试器的礼物吧。

The problem is that if I print out the variables using ostream in C++ it treats it as char. If I have:

问题是,如果我在 C++ 中使用 ostream 打印出变量,它会将其视为字符。如果我有:

unsigned char a = 0;
unsigned char b = 0xff;
cout << "a is " << hex << a <<"; b is " << hex << b << endl;

then the output is:

那么输出是:

a is ^@; b is 377

instead of

代替

a is 0; b is ff

I tried using uint8_t, but as I mentioned before, that's typedef'ed to unsigned char, so it does the same. How can I print my variables correctly?

我尝试使用uint8_t,但正如我之前提到的,这是 typedef'ed to unsigned char,所以它做同样的事情。如何正确打印我的变量?

Edit:I do this in many places throughout my code. Is there any way I can do this withoutcasting to inteach time I want to print?

编辑:我在整个代码中的很多地方都这样做。有什么办法可以做到这一点,而不必int每次要打印时都强制转换?

采纳答案by MartinStettner

I would suggest using the following technique:

我建议使用以下技术:

struct HexCharStruct
{
  unsigned char c;
  HexCharStruct(unsigned char _c) : c(_c) { }
};

inline std::ostream& operator<<(std::ostream& o, const HexCharStruct& hs)
{
  return (o << std::hex << (int)hs.c);
}

inline HexCharStruct hex(unsigned char _c)
{
  return HexCharStruct(_c);
}

int main()
{
  char a = 131;
  std::cout << hex(a) << std::endl;
}

It's short to write, has the same efficiency as the original solution and it lets you choose to use the "original" character output. And it's type-safe (not using "evil" macros :-))

它写起来很短,与原始解决方案具有相同的效率,并且可以让您选择使用“原始”字符输出。而且它是类型安全的(不使用“邪恶”宏:-))

回答by MartinStettner

Use:

用:

cout << "a is " << hex << (int) a <<"; b is " << hex << (int) b << endl;

And if you want padding with leading zeros then:

如果你想用前导零填充,那么:

#include <iomanip>
...
cout << "a is " << setw(2) << setfill('0') << hex << (int) a ; 

As we are using C-style casts, why not go the whole hog with terminal C++ badness and use a macro!

当我们使用 C 风格的强制转换时,为什么不完全使用终端 C++ 的坏处并使用宏!

#define HEX( x )
   setw(2) << setfill('0') << hex << (int)( x )

you can then say

然后你可以说

cout << "a is " << HEX( a );

Edit:Having said that, MartinStettner's solution is much nicer!

编辑:话虽如此,MartinStettner 的解决方案要好得多!

回答by ltc

You can read more about this at http://cpp.indi.frih.net/blog/2014/09/tippet-printing-numeric-values-for-chars-and-uint8_t/and http://cpp.indi.frih.net/blog/2014/08/code-critique-stack-overflow-posters-cant-print-the-numeric-value-of-a-char/. I am only posting this because it has become clear that the author of the above articles does not intend to.

您可以在http://cpp.indi.frih.net/blog/2014/09/tippet-printing-numeric-values-for-chars-and-uint8_t/http://cpp.indi阅读更多相关信息。 frih.net/blog/2014/08/code-critique-stack-overflow-posters-cant-print-the-numeric-value-of-a-char/。我发布这个只是因为很明显,上述文章的作者并不打算这样做。

The simplest and most correct technique to do print a char as hex is

将字符打印为十六进制的最简单和最正确的技术是

unsigned char a = 0;
unsigned char b = 0xff;
auto flags = cout.flags(); //I only include resetting the ioflags because so
                           //many answers on this page call functions where
                           //flags are changed and leave no way to  
                           //return them to the state they were in before 
                           //the function call
cout << "a is " << hex << +a <<"; b is " << +b << endl;
cout.flags(flags);

The readers digest version of how this works is that the unary + operator forces a no op type conversion to an int with the correct signedness. So, an unsigned char converts to unsigned int, a signed char converts to int, and a char converts to either unsigned int or int depending on whether char is signed or unsigned on your platform (it comes as a shock to many that char is special and not specified as either signed or unsigned).

读者对其工作原理的摘要版本是一元 + 运算符强制将 no op 类型转换为具有正确符号的 int。因此,unsigned char 转换为 unsigned int,signed char 转换为 int,char 转换为 unsigned int 或 int 取决于 char 在您的平台上是有符号还是无符号(这让许多人感到震惊,char 是特殊的并且未指定为有符号或无符号)。

The only negative of this technique is that it may not be obvious what is happening to a someone that is unfamiliar with it. However, I think that it is better to use the technique that is correct and teach others about it rather than doing something that is incorrect but more immediately clear.

这种技术的唯一缺点是,对于不熟悉它的人来说,发生的事情可能并不明显。但是,我认为最好使用正确的技术并教给其他人,而不是做一些不正确但更直观的事情。

回答by VinGarcia

Well, this works for me:

嗯,这对我有用:

std::cout << std::hex << (0xFF & a) << std::endl;

If you just cast (int)as suggested it might add 1s to the left of aif its most significant bit is 1. So making this binary AND operation guarantees the output will have the left bits filled by 0s and also converts it to unsigned int forcing cout to print it as hex.

如果您只是(int)按照建议进行转换,则它可能会a在其最高有效位为 1的左侧添加 1 。它作为十六进制。

I hope this helps.

我希望这有帮助。

回答by fredoverflow

Hm, it seems I re-invented the wheel yesterday... But hey, at least it's a generic wheel this time :) chars are printed with two hex digits, shorts with 4 hex digits and so on.

嗯,看来我昨天重新发明了轮子……但是,嘿,至少这次是一个通用轮子:) chars 用两个十六进制数字打印,shorts 用 4 个十六进制数字打印,依此类推。

template<typename T>
struct hex_t
{
    T x;
};

template<typename T>
hex_t<T> hex(T x)
{
    hex_t<T> h = {x};
    return h;
}

template<typename T>
std::ostream& operator<<(std::ostream& os, hex_t<T> h)
{
    char buffer[2 * sizeof(T)];
    for (auto i = sizeof buffer; i--; )
    {
        buffer[i] = "0123456789ABCDEF"[h.x & 15];
        h.x >>= 4;
    }
    os.write(buffer, sizeof buffer);
    return os;
}

回答by tdihp

I think TrungTN and anon's answer is okay, but MartinStettner's way of implementing the hex() function is not really simple, and too dark, considering hex << (int)mychar is already a workaround.

我认为 TrungTN 和 anon 的答案是可以的,但是 MartinStettner 实现 hex() 函数的方式并不是很简单,而且太暗了,考虑到 hex << (int)mychar 已经是一种解决方法。

here is my solution to make "<<" operator easier:

这是我使“<<”运算符更容易的解决方案:

#include <sstream>
#include <iomanip>

string uchar2hex(unsigned char inchar)
{
  ostringstream oss (ostringstream::out);
  oss << setw(2) << setfill('0') << hex << (int)(inchar);
  return oss.str();
}

int main()
{
  unsigned char a = 131;
  std::cout << uchar2hex(a) << std::endl;
}

It's just not worthy implementing a stream operator :-)

只是不值得实现流运算符:-)

回答by Jimmy J

I'd do it like MartinStettner but add an extra parameter for number of digits:

我会像 MartinStettner 那样做,但为位数添加一个额外的参数:

inline HexStruct hex(long n, int w=2)
{
  return HexStruct(n, w);
}
// Rest of implementation is left as an exercise for the reader

So you have two digits by default but can set four, eight, or whatever if you want to.

因此,默认情况下您有两位数字,但可以设置四位、八位或任何您想要的数字。

eg.

例如。

int main()
{
  short a = 3142;
  std:cout << hex(a,4) << std::endl;
}

It may seem like overkill but as Bjarne said: "libraries should be easy to use, not easy to write".

这似乎有点矫枉过正,但正如 Bjarne 所说:“库应该易于使用,而不是易于编写”。

回答by drus

I use the following on win32/linux(32/64 bit):

我在 win32/linux(32/64 位)上使用以下内容:

#include <iostream>
#include <iomanip>

template <typename T>
std::string HexToString(T uval)
{
    std::stringstream ss;
    ss << "0x" << std::setw(sizeof(uval) * 2) << std::setfill('0') << std::hex << +uval;
    return ss.str();
}

回答by nikolajsheller

I would suggest:

我会建议:

std::cout << setbase(16) << 32;

Taken from: http://www.cprogramming.com/tutorial/iomanip.html

摘自:http: //www.cprogramming.com/tutorial/iomanip.html

回答by TrungTN

You can try the following code:

您可以尝试以下代码:

unsigned char a = 0;
unsigned char b = 0xff;
cout << hex << "a is " << int(a) << "; b is " << int(b) << endl;
cout << hex
     <<   "a is " << setfill('0') << setw(2) << int(a)
     << "; b is " << setfill('0') << setw(2) << int(b)
     << endl;
cout << hex << uppercase
     <<   "a is " << setfill('0') << setw(2) << int(a)
     << "; b is " << setfill('0') << setw(2) << int(b)
     << endl;

Output:

输出:

a is 0; b is ff

a is 0; b is ff

a is 00; b is ff

a is 00; b is ff

a is 00; b is FF

a is 00; b is FF