HOWTO · C++

Konvertieren von String in Hex in C++

Dieser Artikel stellt vor, wie man in C++ einen String in einen Hexadezimalwert konvertiert

Auf dieser Seite

Die Konvertierung eines std::string in eine Hexadezimaldarstellung in C++ bedeutet, eine Textdarstellung der Bytes des Strings zu erzeugen: Jeder char wird zu einem zweistelligen Wert zur Basis 16, sodass aus \"Hello\" 48656c6c6f wird. Sie benötigen das zum Debuggen binärer Daten, zum Erzeugen von Prüfsummen oder Fingerabdrücken sowie für Protokolle, die hexadezimal kodierte Nutzdaten erwarten.

Dieser Artikel zeigt, wie Sie Hexadezimalausgaben direkt ausgeben, einen wiederverwendbaren hexadezimalen std::string aufbauen, jedes Byte zweistellig halten und das Ergebnis zur Textkodierung in Beziehung setzen; anschließend vergleicht er die Ansätze, damit Sie den passenden auswählen können.

Einen String in hexadezimale Bytes konvertieren

Der direkteste Ansatz durchläuft die Eingabe Byte für Byte und schreibt jeden Wert zur Basis 16 nach std::cout. Der Stream-Manipulator std::hex schaltet die Ganzzahlausgabe auf Hexadezimaldarstellung um, und std::setw(2) hält zusammen mit std::setfill('0') jedes Byte zweistellig. Die Iteration mit unsigned char hält jedes Byte im Bereich 0–255, sodass Bytes über 0x7f auch auf Plattformen korrekt formatiert werden, auf denen einfaches char vorzeichenbehaftet ist. Führen Sie dieses Beispiel aus:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

#include <iomanip>
#include <iostream>
#include <string>

int main() {
    std::string input = "Hello";

    std::cout << std::hex << std::setfill('0');
    for (unsigned char c : input) {
        std::cout << std::setw(2) << static_cast<int>(c);
    }
    std::cout << '\n';
}
48656c6c6f

std::hex bleibt wirksam, bis Sie ihn ändern; setzen Sie ihn daher einmal vor der Schleife. std::setw(2) gilt nur für den nächsten eingefügten Wert und steht deshalb innerhalb der Schleife, während std::setfill('0') bestehen bleibt. Die Ausgabe über std::cout eignet sich gut für eine schnelle Kontrolle, doch der konvertierte Text geht verloren, sobald er aus dem sichtbaren Bereich scrollt — der nächste Abschnitt speichert ihn.

Einen hexadezimalen String erstellen und speichern

Wenn der konvertierte Text später benötigt wird — etwa als Rückgabewert einer Funktion, als Ergänzung einer Protokollnachricht oder zum Schreiben in eine Datei —, sammeln Sie ihn in einem std::stringstream statt in std::cout. Dieselben Formatierungsmanipulatoren gelten, und str() erzeugt einen std::string, der das Ergebnis enthält:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

std::string toHex(const std::string& input) {
    std::stringstream ss;
    ss << std::hex << std::setfill('0');
    for (unsigned char c : input) {
        ss << std::setw(2) << static_cast<int>(c);
    }
    return ss.str();
}

int main() {
    std::string text = "C++ Programming";
    std::string hexText = toHex(text);
    std::cout << "string: " << text << '\n';
    std::cout << "hexval: " << hexText << '\n';
}
string: C++ Programming
hexval: 432b2b2050726f6772616d6d696e67

Da toHex einen std::string zurückgibt, entscheidet der Aufrufer, was damit geschieht: ausgeben, speichern oder an einen Dateistream übergeben. Das unveränderte Beispiel gibt den Wert nur aus — die Bezeichnungen string: und hexval: in seiner Ausgabe bleiben Englisch. Das Schreiben in eine Datei ist ein separater Schritt über std::ofstream, der denselben Hexadezimaltext akzeptiert.

Jedes Byte mit zwei Hexadezimalziffern formatieren

Ein Byte enthält einen Wert von 0 bis 255 — 0x00 bis 0xff —, sodass zwei Ziffern immer ausreichen. Ohne Auffüllung werden Werte unter 0x10 einstellig ausgegeben, was die Ausgabe mehrdeutig macht: Das Bytepaar 0x01, 0x0a und das einzelne Byte 0x1a würden beide 1a ergeben. std::setw(2) legt die minimale Feldbreite fest, und std::setfill('0') liefert das Füllzeichen:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

#include <iomanip>
#include <iostream>
#include <string>

int main() {
    std::string input = "A\nB";

    std::cout << std::hex << std::setfill('0');
    for (unsigned char c : input) {
        std::cout << std::setw(2) << static_cast<int>(c);
    }
    std::cout << '\n';
}
410a42

Das mittlere Byte ist 0x0a und wird dennoch zweistellig ausgegeben. Entfernen Sie std::setw und std::setfill, gibt dieselbe Eingabe 41a42 aus, bei der nicht mehr erkennbar ist, wo ein Byte endet und das nächste beginnt. Behalten Sie std::setw innerhalb der Schleife — es wird nach jedem formatierten Wert zurückgesetzt —, während std::setfill nur einmal gesetzt werden muss.

Bytewerte und Textkodierung verstehen

Alle bisherigen Beispiele konvertieren Bytes, nicht Zeichen. std::string speichert eine Folge von char, und die Schleife formatiert den numerischen Wert jedes Elements. Bei ASCII-Eingaben ist dieser Unterschied unsichtbar — H ist das einzelne Byte 0x48 —, für anderen Text ist er jedoch wichtig. In UTF-8 wird é (Codepunkt U+00E9) als die zwei Bytes 0xc3 0xa9 gespeichert, sodass dieselbe Schleife c3a9 statt e9 erzeugt:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

#include <iomanip>
#include <iostream>
#include <string>

int main() {
    std::string input = "\xc3\xa9";  // UTF-8 bytes for U+00E9

    std::cout << std::hex << std::setfill('0');
    for (unsigned char c : input) {
        std::cout << std::setw(2) << static_cast<int>(c);
    }
    std::cout << '\n';
}
c3a9

Die Funktionen in diesem Artikel beschreiben daher die kodierten Bytes dessen, was der String gerade enthält. Wenn Sie stattdessen hexadezimale Codepunkte benötigen, dekodieren Sie den Text zuerst und formatieren die dekodierten Werte. Der englische Kommentar // UTF-8 bytes for U+00E9 im unveränderten Codebeispiel weist nur darauf hin, dass das String-Literal die UTF-8-Bytes für U+00E9 enthält. Die Behandlung vorzeichenloser Bytes ist aus demselben Grund wichtig: Wo einfaches char vorzeichenbehaftet ist, wird ein Byte wie 0xc3 in einen Wert unter null umgewandelt und als ffffffc3 ausgegeben. Die Iteration mit unsigned char — oder eine Umwandlung über diesen Typ vor static_cast<int> — hält den Wert bei 0xc3.

Einen Konvertierungsansatz auswählen

Verwenden Sie die direkte std::cout-Schleife, wenn Sie Daten nur einmal prüfen müssen. Geben Sie einen mit std::stringstream erstellten std::string zurück, wenn das Ergebnis über den Aufruf hinaus bestehen muss — das ist die am besten lesbare Allzwecklösung und bündelt die Formatierung mit std::hex, std::setw und std::setfill an einer Stelle.

Eine dritte Option zerlegt jedes Byte in seine beiden 4-Bit-Hälften (Nibbles) und bildet jede über eine Nachschlagetabelle ab:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

#include <iostream>
#include <string>

std::string toHexLookup(const std::string& input) {
    static const char digits[] = "0123456789abcdef";
    std::string result;
    result.reserve(input.size() * 2);
    for (unsigned char c : input) {
        result += digits[c >> 4];
        result += digits[c & 0x0f];
    }
    return result;
}

int main() {
    std::cout << toHexLookup("World") << '\n';
}
576f726c64

Die Nachschlagetabellen-Variante gibt immer genau zwei Ziffern pro Byte aus und führt keine Stream-Formatierung durch, was manche Codebasen der Einheitlichkeit halber bevorzugen. Ob sie schneller läuft, hängt von Ihrer Standardbibliotheksimplementierung ab; messen Sie daher mit Ihren eigenen Daten, falls das wichtig ist. Unabhängig vom gewählten Ansatz beschreibt das Ergebnis Bytes: Bei ASCII-Text liest es sich als ein Paar pro Zeichen und bei UTF-8- oder Binärdaten als ein Paar pro kodiertem Byte.