2009-12-28 9 views
9

Ich frage mich, wie man eine hexadezimale Zeichenfolge in eine lesbare Zeichenfolge konvertiert (wenn das irgendeinen Sinn macht), wäre dies meine erste echte Begegnung mit Hexadezimalwerten, also lerne ich immer noch über sie und wie zu verwalten Sie.C++ Hex-Parsing

Ich habe ein Programm, das Daten aus einer Datei liest, die rohe Paketdaten (hex) enthält, und ich muss diese Informationen analysieren, damit es lesbar ist.

Ein Beispiel von dem, was ich tun muss, ist etwas wie diese Seite tut http://home2.paulschou.net/tools/xlate/, wo Sie in hex einfügen und es in Text umgewandelt werden kann.

+1

Um zu verdeutlichen: Sie wollen Binärdaten nehmen und im Hex-Format anzeigen? – James

+0

Ich möchte rohe Paketdaten, die in Hex gespeichert sind, und wandeln es von Hex in ein für Menschen lesbares Format. – Undawned

+0

Rohdaten sind im Wesentlichen binär, Hexadezimal ist nur eine einfachere Möglichkeit, es zu lesen, da alle vier Binärziffern als eine einzelne Hexadezimalzahl gelesen werden können. – phoebus

Antwort

3

Die C++ - ish Weg, um eine Zeichenfolge, die die hexadezimale Darstellung einer bestimmten Zahl zu erhalten, ist die hex Modifikator für Ströme zu verwenden, wie in diesem Beispiel:

const int i = 0xdeadbeef; 
cout << "0x" << hex << i << endl; // prints "0xdeadbeef" 

Sie den gleichen Modifikator auf Zeichenfolge verwenden können, Ströme auf, falls Sie die hexadezimale Darstellung in einer String-variablen haben:

const int i = 0xdeadc0de; 
ostringstream stream; 
stream << "0x" << hex << i; 

const string s = stream.str(); // s now contains "0xdeadc0de" 

UPDATE:

Wenn Ihre Eingabedaten als Zeichenfolge mit der hexadezimalen Darstellung der Zeichen einer Zeichenfolge angegeben werden, müssen Sie die Codierung der Eingabezeichenfolge kennen, um sie korrekt anzuzeigen. Im einfachsten Fall ist die Zeichenkette etwas wie ASCII, das ein Byte einem Zeichen zuordnet. In einer gegebenen Eingabe "414243" werden also alle zwei Zeichen ("41", "42", "43) einem ASCII-Wert (65, 66, 67) zugeordnet, der auf ein Zeichen (" A "," B ") ., "C")

Hier ist, wie das in C++:

const string hexData = "414243"; 

assert(hexData.size() % 2 == 0); 

ostringstream asciiStream; 
istringstream hexDataStream(hexData); 
vector<char> buf(3); // two chars for the hex char, one for trailing zero 
while (hexDataStream.good()) { 
    hexDataStream.get(&buf[0], buf.size()); 
    if (hexDataStream.good()) { 
     asciiStream << static_cast<char>(std::strtol(&buf[0], 0, 16)); 
    } 
} 

const string asciiData = asciiStream.str(); // asciiData == "ABC" 

mit std::strtol von <cstdlib> macht dies einfach, wenn Sie eine Template-Klasse zur Verwendung für diese darauf bestehen, std :: string verwenden ausführen die Umwandlung der einzelnen Sub-Strings (wie "41") in Dezimalwerte (65).

+1

Ich bin ein wenig verwirrt, alles, was zu tun scheint, speichert das Hex in eine Zeichenfolge? Ich muss die Hex-Daten in eine lesbare Zeichenfolge aus konvertieren Seine hex Daten, wie http://home2.paulschou.net/tools/xlate/ diese Art von Website tut. – Undawned

+0

Es gibt die hexadezimale Darstellung einer Zahl, richtig . Was meinst du mit 'Hexendaten'? Sind die Eingabedaten eine Zeichenfolge mit den Zeichen "414243", und möchten Sie diese z. "ABC" (weil das die Website tut)? –

+0

Ja, ich mag es konvertieren „ABC“ diese 1062000000000002000100024177616b656e65642d4465760036372e3232382e35302e3232333a38303835000000000009022c010000576f575472616e63652d4177616b656e696e670036372e3232382e34392e39303a3830383500000000000a einige Strings enthält und eine IP-Adresse des Servers, die ich von den Daten bekam, würde Ich mag die obigen Daten in ein Format konvertieren zu können, dass ich die Werte lesen es hält. – Undawned

0
fprintf(file, "%h", thing); 

Etwas in diese Richtung?

0

Hex ist eine Möglichkeit zur Anzeige von Binärdaten.Es ist nicht "Rohdaten" wie Sie sagen.Wenn die Rohdaten Sie haben enthält eine Zeichenfolge, Sie sollten Sie können die Zeichenfolge (möglicherweise zusammen mit anderem Papierkorb) anzeigen, wenn Sie sie auf dem Bildschirm ausgeben.

Hier ist eine Schleife, um die ASCII-Zeichen in einem Datenblock zu drucken. Um etwas anderes zu bekommen, müssen Sie mit seinem Format umgehen.

+0

Dies ist keine Antwort auf die Frage, Sie versuchen, ASCII-Zeichen zu finden und anzuzeigen. Warum weisen Sie beim Lesen von Zeichen einen Zeigerpuffer zu? Warum versuchen Sie, die Adresse dieses Pointer-Arrays dem Char-Pointer zuzuweisen (sollte nicht kompiliert werden)? Warum verwendest du die Fehlerausgabe? – harper

+0

@Harper: Ich vermutete, dass er hinsichtlich der Natur von Binärdaten verwirrt war und dass er keine Textdaten hatte, die als Hexadezimal-ASCII kodiert waren. Um den Textteil einiger Daten, die Sie sonst mit einem anderen Programm als hexadezimal ansehen, zu drucken, würden Sie die Nicht-ASCII-Zeichen überspringen. Der Puffer von Zeigern ist ein Tippfehler, sollte einfacher Zeichenpuffer sein. Die Fehlerausgabe ist, weil ich diese Art von Dingen mit dem Debugging assoziiere, und ich benutze 'cerr' zum Debuggen, um zu vermeiden, dass die" reale "Ausgabe eines Programms gestört wird. – Potatoswatter

11

Aus der Bibliothek C++ String Toolkit Library (StrTk) entnommen, sollte das Folgende ausreichen. Beachten Sie, dass out auf ein Speicherstück zeigen sollte, das halb so groß ist wie std :: distance (Anfang, Ende) und dass die Werte im Bereich von [Anfang, Ende] 0-9A-F oder 0-9a-f sind

inline bool convert_hex_to_bin(const unsigned char* begin, 
           const unsigned char* end, 
           unsigned char* out) 
    { 
     if (std::distance(begin,end) % 2) 
      return false; 
     static const std::size_t symbol_count = 256; 
     static const unsigned char hex_to_bin[symbol_count] = { 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 - 0x07 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 - 0x0F 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 - 0x17 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 - 0x1F 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 - 0x27 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 - 0x2F 
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 0x30 - 0x37 
        0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 - 0x3F 
        0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, // 0x40 - 0x47 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 - 0x4F 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 - 0x57 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 - 0x5F 
        0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, // 0x60 - 0x67 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 - 0x6F 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 - 0x77 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 - 0x7F 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 - 0x87 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 - 0x8F 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 - 0x97 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 - 0x9F 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 - 0xA7 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 - 0xAF 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 - 0xB7 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 - 0xBF 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 - 0xC7 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 - 0xCF 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 - 0xD7 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 - 0xDF 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 - 0xE7 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 - 0xEF 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 - 0xF7 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0xF8 - 0xFF 
        }; 

     const unsigned char* itr = begin; 
     while (end != itr) 
     { 
      (*out) = static_cast<unsigned char>(hex_to_bin[*(itr++)] << 4); 
      (*out) |= static_cast<unsigned char>(hex_to_bin[*(itr++)] ); 
      ++out; 
     } 
     return true; 
    }