Подтвердить что ты не робот

Как я могу печатать байты как шестнадцатеричные?

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

С

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

}

С++:

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

Ответ 4

Печать произвольных структур в современном С++

Все ответы до сих пор говорят только, как печатать массив целых чисел, но мы также можем печатать любую произвольную структуру, учитывая, что мы знаем ее размер. Пример ниже создает такую ​​структуру и выполняет итерацию указателя через его байты, печатая их на выходе:

#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.

Также обратите внимание, что все значения представлены как little endian (на первый взгляд появляются младшие значащие байты), поскольку он был скомпилирован и запущен на Intel платформы.

Ответ 5

Это модифицированная версия метода 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;
    }
}

Ответ 6

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

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

Вы можете ускорить его, используя метод Nibble to Hex

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

}

Ответ 7

Использовать потоки C++ и восстановить состояние потом

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

main.cpp

#include <iomanip>
#include <iostream>

int main() {
    int array[] = {0, 0x8, 0x10, 0x18};
    constexpr size_t size = sizeof(array) / sizeof(array[0]);

    // Sanity check decimal print.
    for (size_t i = 0; i < size; ++i)
        std::cout << array[i] << " ";
    std::cout << std::endl;

    // Hex print and restore default afterwards.
    std::ios cout_state(nullptr);
    cout_state.copyfmt(std::cout);
    std::cout << std::hex << std::setfill('0') << std::setw(2);
    for (size_t i = 0; i < size; ++i)
        std::cout << array[i] << " ";
    std::cout << std::endl;
    std::cout.copyfmt(cout_state);

    // Check that cout state was restored.
    for (size_t i = 0; i < size; ++i)
        std::cout << array[i] << " ";
    std::cout << std::endl;
}

Скомпилировать и запустить:

g++ -o main.out -std=c++11 main.cpp
./main.out

Выход:

0 8 16 24 
00 8 10 18 
0 8 16 24

Протестировано на Ubuntu 16.04, GCC 6.4.0.