wake-up-neo.com

Wie drucke ich Bytes als Hexadezimalzahl?

Ich weiß, dass Sie in C # die Methode String.Format verwenden können. Aber wie machen Sie das in C++? Gibt es eine Funktion, mit der ich ein Byte in ein Hex konvertieren kann? Sie müssen nur 8 Byte lange Daten in Hex konvertieren. Wie mache ich das?

25
Danny

Nun, Sie können jeweils ein Byte (unsigned char) in ein Array umwandeln

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

Wenn Sie C++ - Streams anstelle von C-Funktionen verwenden möchten, haben Sie folgende Möglichkeiten:

    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;

Sehr einfach.

Ausgabe:

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

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

Beliebige Strukturen in modernem C++ drucken

Alle Antworten zeigen Ihnen bisher nur, wie Sie ein Array von Ganzzahlen drucken, aber wir können auch jede beliebige Struktur drucken, vorausgesetzt, wir kennen deren Größe. Das folgende Beispiel erstellt eine solche Struktur und durchläuft einen Zeiger durch seine Bytes und gibt sie an die Ausgabe aus:

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

Und hier ist die Ausgabe:

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

Beachten Sie, dass dieses Beispiel auch Speicherausrichtung Arbeit veranschaulicht. Wir sehen, dass version 2 Bytes (05 00) einnimmt, gefolgt von msgSize mit 2 weiteren Bytes (24 00) und dann 4 Byte Auffüllung, worauf someId (34 12 00 00 00 00 00 00) und anotherId (78 56 00 00 00 00 00 00) folgen. Dann isFoo, das 1 Byte (01) und isBar ein anderes Byte (01) einnimmt, gefolgt von 6 Byte Auffüllung, die schließlich mit der IEEE 754-Standarddarstellung des Doppelfelds floatingPointValue endet.

Beachten Sie auch, dass alle Werte als Little Endian (niederwertigste Bytes zuerst) dargestellt werden, da diese auf einer Intel-Plattform kompiliert und ausgeführt wurden.

4
Lucio Paiva

Dies ist eine modifizierte Version der Nibble to Hex-Methode

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;
    }
}
3
Mohamed Saad

Ich kenne keinen besseren Weg als:

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

Sie können es beschleunigen, indem Sie eine Nibble to Hex-Methode verwenden

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

}
2
Rick Murtagh

C++ Streams verwenden und danach den Status wiederherstellen

Dies ist eine Variation von Wie drucke ich Bytes als Hexadezimalzahl? aber:

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

Kompilieren und ausführen:

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

Ausgabe:

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

Getestet auf Ubuntu 16.04, GCC 6.4.0.