如何以十六进制打印字节?

Dan*_*nny 28 c++ bytearray type-conversion data-conversion

我知道在C#中你可以使用String.Format方法.但是你如何在C++中做到这一点?是否有一个函数允许我将一个字节转换为十六进制?只需将8字节长的数据转换为Hex,我该怎么做?

Com*_* 10 61

如果要使用C++流而不是C函数,可以执行以下操作:

int ar[] = { 20, 30, 40, 50, 60, 70, 80, 90 };
const int siz_ar = sizeof(ar) / sizeof(int);

for (int i = 0; i < siz_ar; ++i)
    cout << ar[i] << " ";
cout << endl;

for (int i = 0; i < siz_ar; ++i)
    cout << hex << setfill('0') << setw(2) << ar[i] << " ";
cout << endl;
Run Code Online (Sandbox Code Playgroud)

非常简单.

输出:

20 30 40 50 60 70 80 90
14 1e 28 32 3c 46 50 5a 
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是你应该`#include <iomanip>`并且`hex`,`setfill`和`setw`都在`std`命名空间中.进一步的`hex`是持久的,所以你可以把它拉到循环之外,你应该在完成后调用`dec`,这样流就会以十进制打印未来的积分值,假设这就是你想要的. (32认同)
  • 要解释@Andrew,如果你有一个char c并想要将值> 0x80打印为十六进制,则需要将其转换为(unsigned int)(unsigned char)c.否则你将打印32位2的补码. (4认同)
  • 非常好的答案---它可以使用一些例子``hex``和``setfill``. (2认同)
  • 另外,值得注意的是这些"字节"必须转换为整数格式...... (2认同)
  • @jbr `unsigned char` 不起作用。对于新手来说,如果你有 `char a = 20; cout &lt;&lt; hex &lt;&lt; a &lt;&lt; endl;`,它会给你垃圾。因为“`char` 对于 ostream 有一个特殊的重载,即“operator&lt;&lt;`”。因此,您需要强制转换为“int”,例如“cout &lt;&lt; hex &lt;&lt; (int)a &lt;&lt; endl;”。至于十六进制打印值 &gt; `0x80`,还需要进行转换。原因是[在c中打印十六进制字符](/sf/ask/564211931/)。 (2认同)

ben*_*ech 31

那么你可以一次将一个字节(unsigned char)转换成这样的数组

char buffer [17];
buffer[16] = 0;
for(j = 0; j < 8; j++)
    sprintf(&buffer[2*j], "%02X", data[j]);
Run Code Online (Sandbox Code Playgroud)

  • 我会注意到这是实际的C-way,而不是C++.我宁愿接受@Component 10的答案. (8认同)
  • 如果相关字符为负数,则可变参数函数的类型提升将导致六个前导“F”。 (3认同)

vit*_*aut 19

您可以使用 C++20 来完成此操作,这与C# 中的std::format类似:String.Format

std::string s = std::format("{:x}", std::byte(42)); // s == 2a
Run Code Online (Sandbox Code Playgroud)

std::format广泛使用之前,您可以使用{fmt} 库std::format它基于 ( godbolt ):

std::string s = fmt::format("{:x}", std::byte(42)); // s == 2a
Run Code Online (Sandbox Code Playgroud)

免责声明:我是 {fmt} 和 C++20 的作者std::format


use*_*487 15

C:

static void print_buf(const char *title, const unsigned char *buf, size_t buf_len)
{
    size_t i = 0;
    fprintf(stdout, "%s\n", title);
    for(i = 0; i < buf_len; ++i)
    fprintf(stdout, "%02X%s", buf[i],
             ( i + 1 ) % 16 == 0 ? "\r\n" : " " );

}
Run Code Online (Sandbox Code Playgroud)

C++:

void print_bytes(std::ostream& out, const char *title, const unsigned char *data, size_t dataLen, bool format = true) {
    out << title << std::endl;
    out << std::setfill('0');
    for(size_t i = 0; i < dataLen; ++i) {
        out << std::hex << std::setw(2) << (int)data[i];
        if (format) {
            out << (((i + 1) % 16 == 0) ? "\n" : " ");
        }
    }
    out << std::endl;
}
Run Code Online (Sandbox Code Playgroud)


Luc*_*iva 9

在现代 C++ 中打印任意结构

到目前为止,所有答案都只告诉您如何打印整数数组,但我们也可以打印任何任意结构,前提是我们知道它的大小。下面的例子创建了这样的结构,并通过它的字节迭代一个指针,将它们打印到输出:

#include <iostream>
#include <iomanip>
#include <cstring>

using std::cout;
using std::endl;
using std::hex;
using std::setfill;
using std::setw;

using u64 = unsigned long long;
using u16 = unsigned short;
using f64 = double;

struct Header {
    u16 version;
    u16 msgSize;
};

struct Example {
    Header header;
    u64 someId;
    u64 anotherId;
    bool isFoo;
    bool isBar;
    f64 floatingPointValue;
};

int main () {
    Example example;
    // fill with zeros so padding regions don't contain garbage
    memset(&example, 0, sizeof(Example));
    example.header.version = 5;
    example.header.msgSize = sizeof(Example) - sizeof(Header);
    example.someId = 0x1234;
    example.anotherId = 0x5678;
    example.isFoo = true;
    example.isBar = true;
    example.floatingPointValue = 1.1;

    cout << hex << setfill('0');  // needs to be set only once
    auto *ptr = reinterpret_cast<unsigned char *>(&example);
    for (int i = 0; i < sizeof(Example); i++, ptr++) {
        if (i % sizeof(u64) == 0) {
            cout << endl;
        }
        cout << setw(2) << static_cast<unsigned>(*ptr) << " ";
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

05 00 24 00 00 00 00 00 
34 12 00 00 00 00 00 00 
78 56 00 00 00 00 00 00 
01 01 00 00 00 00 00 00 
9a 99 99 99 99 99 f1 3f
Run Code Online (Sandbox Code Playgroud)

请注意,此示例还说明了内存对齐工作。我们看到version占用了 2 个字节 ( 05 00),然后是另外msgSize2 个字节 ( 24 00),然后是 4 个字节的填充,之后是someId( 34 12 00 00 00 00 00 00) 和anotherId( 78 56 00 00 00 00 00 00)。然后isFoo,它占用 1 个字节 ( 01) 和isBar另一个字节 ( 01),接着是 6 个字节的填充,最后以双字段的 IEEE 754 标准表示结束floatingPointValue

另请注意,所有值都表示为小端(最低有效字节在前),因为这是在 Intel 平台上编译和运行的。