Как печатать байты как шестнадцатеричные?

Я знаю, что в C# Вы можете использовать строку.Способ формате. Но как это сделать на C++? Есть ли функция, которая позволяет мне конвертировать байт в Hex?? Просто нужно преобразовать данные длиной 8 байт в Hex, как это сделать?

6 ответов


Ну, вы можете конвертировать один байт (без знака char) за раз в массив, как так

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

Если вы хотите использовать потоки 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;

очень удобно.

выход:

20 30 40 50 60 70 80 90
14 1e 28 32 3c 46 50 5a 

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" : " " );

}

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;
}

Это модифицированная версия метода Nibble to Hex

void hexArrayToStr(unsigned char* info, unsigned int infoLength, char **buffer) {
    const char* pszNibbleToHex = {"0123456789ABCDEF"};
    int nNibble, i;
    if (infoLength > 0) {
        if (info != NULL) {
            *buffer = (char *) malloc((infoLength * 2) + 1);
            buffer[0][(infoLength * 2)] = 0;
            for (i = 0; i < infoLength; i++) {
                nNibble = info[i] >> 4;
                buffer[0][2 * i] = pszNibbleToHex[nNibble];
                nNibble = info[i] & 0x0F;
                buffer[0][2 * i + 1] = pszNibbleToHex[nNibble];
            }
        } else {
            *buffer = NULL;
        }
    } else {
        *buffer = NULL;
    }
}

печать произвольных структур в современном 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;
}

и вот результат:

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

обратите внимание, что этот пример также иллюстрирует выравнивание памяти работает. Мы видим version занимает 2 байта (05 00), далее msgSize С 2 байта (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.


Я не знаю лучшего способа, чем:

unsigned char byData[xxx]; 

int nLength = sizeof(byData) * 2;
char *pBuffer = new char[nLength + 1];
pBuffer[nLength] = 0;
for (int i = 0; i < sizeof(byData); i++)
{
    sprintf(pBuffer[2 * i], "%02X", byData[i]);
}

вы можете ускорить его, используя грызть шестнадцатеричный метод

unsigned char byData[xxx];

const char szNibbleToHex = { "0123456789ABCDEF" };

int nLength = sizeof(byData) * 2;
char *pBuffer = new char[nLength + 1];
pBuffer[nLength] = 0;
for (int i = 0; i < sizeof(byData); i++)
{
    // divide by 16
    int nNibble = byData[i] >> 4;
    pBuffer[2 * i]  = pszNibbleToHex[nNibble];

    nNibble = byData[i] & 0x0F;
    pBuffer[2 * i + 1]  = pszNibbleToHex[nNibble];

}