C++ konvertiert Hex-String in vorzeichenbehaftete Ganzzahl

Lesezeit: 8 Minuten

Ich möchte eine Hex-Zeichenfolge in C++ in eine vorzeichenbehaftete 32-Bit-Ganzzahl konvertieren.

So habe ich zum Beispiel den Hex-String “fffefffe”. Die binäre Darstellung davon ist 1111111111111110111111111111110. Die vorzeichenbehaftete ganzzahlige Darstellung davon ist: -65538.

Wie mache ich diese Konvertierung in C++? Dies muss auch für nicht negative Zahlen funktionieren. Zum Beispiel die Hex-Zeichenfolge „0000000A“, die binär 0000000000000000000000000001010 und 10 dezimal ist.

  • Notiz. Sie erhalten nur -65538 für Systeme mit sizeof(int) == 4

    – Martin York

    1. Juli 2009 um 18:39 Uhr

  • @ Martin York, Er hat es nicht erwähnt int. “32-Bit-Ganzzahl mit Vorzeichen” könnte int32_t oder __int32 usw. sein.

    – Kirill W. Ljadwinski

    1. Juli 2009 um 18:47 Uhr

  • Verwandte Informationen finden Sie unter Hexadezimalzeichenfolge mit führendem „0x“ in einen signierten Short in C++ konvertieren?

    – jww

    7. Mai 2017 um 4:53 Uhr


C konvertiert Hex String in vorzeichenbehaftete Ganzzahl
Evan Teran

verwenden std::stringstream

unsigned int x;   
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;

das folgende Beispiel erzeugt -65538 als Ergebnis:

#include <sstream>
#include <iostream>

int main() {
    unsigned int x;   
    std::stringstream ss;
    ss << std::hex << "fffefffe";
    ss >> x;
    // output it as a signed type
    std::cout << static_cast<int>(x) << std::endl;
}

Im neuen C++11-Standard gibt es einige neue Hilfsfunktionen, die Sie nutzen können! Insbesondere gibt es eine Familie von “String to Number” -Funktionen (http://en.cppreference.com/w/cpp/string/basic_string/stol und http://en.cppreference.com/w/cpp/string/basic_string/stoul). Dies sind im Wesentlichen dünne Hüllen um die Konvertierungsfunktionen von Zeichenfolgen in Zahlen von C, aber wissen, wie man mit a umgeht std::string

Die einfachste Antwort für neueren Code würde also wahrscheinlich so aussehen:

std::string s = "0xfffefffe";
unsigned int x = std::stoul(s, nullptr, 16);

HINWEIS: Unten ist meine ursprüngliche Antwort, die, wie die Bearbeitung sagt, keine vollständige Antwort ist. Für eine funktionierende Lösung kleben Sie den Code über die Zeile :-).

Es scheint, dass seit lexical_cast<> ist so definiert, dass es eine Stream-Umwandlungssemantik hat. Leider verstehen Streams die “0x”-Notation nicht. Also sowohl die boost::lexical_cast und meine handgerollte kommt nicht gut mit Hex-Saiten zurecht. Die obige Lösung, die den Eingabestrom manuell auf Hex setzt, wird damit gut umgehen.

Boost hat einige Sachen um dies ebenfalls zu tun, was auch einige nette Fehlerüberprüfungsfunktionen hat. Sie können es wie folgt verwenden:

try {
    unsigned int x = lexical_cast<int>("0x0badc0de");
} catch(bad_lexical_cast &) {
    // whatever you want to do...
}

Wenn Sie keine Lust haben, Boost zu verwenden, finden Sie hier eine leichte Version der lexikalischen Umwandlung, die keine Fehlerprüfung durchführt:

template<typename T2, typename T1>
inline T2 lexical_cast(const T1 &in) {
    T2 out;
    std::stringstream ss;
    ss << in;
    ss >> out;
    return out;
}

die Sie so verwenden können:

// though this needs the 0x prefix so it knows it is hex
unsigned int x = lexical_cast<unsigned int>("0xdeadbeef"); 

  • Wenn ich diese Methode verwende, erhalte ich am Ende einen ganzzahligen Wert von 152144602

    – Clayton

    1. Juli 2009 um 18:03 Uhr

  • @jmanning2k, ja, es ist seltsam, dass sowohl boost als auch mein lexical_cast auf Hex-Strings (sogar mit dem 0x-Präfix) barf, wenn ich std::hex nicht in den String setze.

    – Evan Teran

    1. Juli 2009 um 18:11 Uhr

  • @SteveWilkinson: Lies den Absatz, der mit dem „BEARBEITEN“. Es erklärt, wie Sie verwenden müssen std::hex

    – Evan Teran

    4. Januar 2012 um 14:58 Uhr

  • Zum stringstreams sollte man prüfen ss.good() && ss.eof() um sicherzustellen, dass keine Fehler aufgetreten sind.

    – atoMerz

    18. Mai 2014 um 6:39 Uhr


  • Dieser “Stoul” rettet meine Logik

    – Vincenzopalazzo

    18. September 2019 um 21:31 Uhr

Für eine Methode, die sowohl mit C als auch mit C++ funktioniert, sollten Sie die Verwendung der Standardbibliotheksfunktion strtol() in Betracht ziehen.

#include <cstdlib>
#include <iostream>
using namespace std;

int main() {
    string s = "abcd";
    char * p;
    long n = strtol( s.c_str(), & p, 16 );
    if ( * p != 0 ) { //my bad edit was here
        cout << "not a number" << endl;
    }
    else {
        cout << n << endl;
    }
}

  • Du solltest benutzen strtoul nicht strtol. Es wird____geben + overflow bei Verwendung von strtol. Mit strtoul Es gibt keinen Überlauf und der zurückgegebene Wert wird konvertiert long korrektes Ergebnis zu erzeugen (-65538). Also deine Antwort fast richtig 🙂

    – Kirill W. Ljadwinski

    1. Juli 2009 um 18:36 Uhr

  • +1. Weil strtol (oder strtoul) schneller ist als die Verwendung von stringstream.

    – Kirill W. Ljadwinski

    1. Juli 2009 um 18:43 Uhr

Andy Buchanan, was das Festhalten an C++ betrifft, ich mochte deine, aber ich habe ein paar Mods:

template <typename ElemT>
struct HexTo {
    ElemT value;
    operator ElemT() const {return value;}
    friend std::istream& operator>>(std::istream& in, HexTo& out) {
        in >> std::hex >> out.value;
        return in;
    }
};

Gebraucht wie

uint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");

Auf diese Weise benötigen Sie kein Impl pro Int-Typ.

  • Ich hätte diesen Schritt auch gemacht, aber ich finde, dass ich die Verbreitung von spitzen Klammern gerne begrenzen möchte. Für diesen Fall hielt ich es für gerechtfertigt, die Regel “Code nicht duplizieren” zu brechen. 🙂

    – Andy J. Buchanan

    15. Juli 2010 um 7:30 Uhr

  • Schade, dass es notwendig ist, aber schön gemacht. Zu meinem persönlichen STL/Boost-Erweiterungen/Korrekturen-Header hinzugefügt. Danke!

    – Tim Sylvester

    5. Oktober 2011 um 0:44 Uhr

  • Leider funktioniert dies nur bei unsignierter Konvertierung. Sie können also 0xFFFFFFFF nicht in -1 umwandeln.

    – fmuecke

    29. Februar 2012 um 7:44 Uhr

  • @fmuecke: Das liegt daran, dass 0xFFFFFFFF ein vorzeichenbehafteter Ganzzahlüberlauf ist, was ein undefiniertes Verhalten ist.

    – Billy ONeal

    13. März 2012 um 16:33 Uhr

1647177007 335 C konvertiert Hex String in vorzeichenbehaftete Ganzzahl
Kirill V. Ljadwinski

Arbeitsbeispiel mit strtoul wird sein:

#include <cstdlib>
#include <iostream>
using namespace std;

int main() { 
    string s = "fffefffe";
    char * p;
    long n = strtoul( s.c_str(), & p, 16 ); 
    if ( * p != 0 ) {  
        cout << "not a number" << endl;
    }    else {  
        cout << n << endl;
    }
}

strtol konvertiert string zu long. Auf meinem Computer numeric_limits<long>::max() gibt 0x7fffffff. Offensichtlich das 0xfffefffe ist größer als 0x7fffffff. Damit strtol kehrt zurück MAX_LONG statt gewollter Wert. strtoul konvertiert string zu unsigned long deshalb kein Überlauf in diesem Fall.

OK, strtol betrachtet die Eingabezeichenfolge vor der Konvertierung nicht als 32-Bit-Ganzzahl mit Vorzeichen. Lustige Probe mit strtol:

#include <cstdlib>
#include <iostream>
using namespace std;

int main() { 
    string s = "-0x10002";
    char * p;
    long n = strtol( s.c_str(), & p, 16 ); 
    if ( * p != 0 ) {  
        cout << "not a number" << endl;
    }    else {  
        cout << n << endl;
    }
}

Der obige Code wird gedruckt -65538 in Konsole.

Hier ist eine einfache und funktionierende Methode, die ich an anderer Stelle gefunden habe:

string hexString = "7FF";
int hexNumber;
sscanf(hexString.c_str(), "%x", &hexNumber);

Bitte beachten Sie, dass Sie möglicherweise lieber unsigned long integer/long integer verwenden, um den Wert zu erhalten. Eine weitere Anmerkung: Die Funktion c_str() konvertiert nur den std::string in const char* .

Wenn Sie also ein const char* bereit haben, verwenden Sie einfach diesen Variablennamen direkt, wie unten gezeigt [I am also showing the usage of the unsigned long variable for a larger hex number. Do not confuse it with the case of having const char* instead of string]:

const char *hexString = "7FFEA5"; //Just to show the conversion of a bigger hex number
unsigned long hexNumber; //In case your hex number is going to be sufficiently big.
sscanf(hexString, "%x", &hexNumber);

Dies funktioniert einwandfrei (vorausgesetzt, Sie verwenden die entsprechenden Datentypen für Ihre Anforderungen).

Ich hatte heute das gleiche Problem, hier ist, wie ich es gelöst habe, damit ich lexical_cast<> behalten konnte

typedef unsigned int    uint32;
typedef signed int      int32;

class uint32_from_hex   // For use with boost::lexical_cast
{
    uint32 value;
public:
    operator uint32() const { return value; }
    friend std::istream& operator>>( std::istream& in, uint32_from_hex& outValue )
    {
        in >> std::hex >> outValue.value;
    }
};

class int32_from_hex   // For use with boost::lexical_cast
{
    uint32 value;
public:
    operator int32() const { return static_cast<int32>( value ); }
    friend std::istream& operator>>( std::istream& in, int32_from_hex& outValue )
    {
        in >> std::hex >> outvalue.value;
    }
};

uint32 material0 = lexical_cast<uint32_from_hex>( "0x4ad" );
uint32 material1 = lexical_cast<uint32_from_hex>( "4ad" );
uint32 material2 = lexical_cast<uint32>( "1197" );

int32 materialX = lexical_cast<int32_from_hex>( "0xfffefffe" );
int32 materialY = lexical_cast<int32_from_hex>( "fffefffe" );
// etc...

(Fand diese Seite, als ich nach einem weniger nervigen Weg suchte 🙂

Gruß, A.

1647177007 341 C konvertiert Hex String in vorzeichenbehaftete Ganzzahl
Mike

Das hat bei mir funktioniert:

string string_test = "80123456";
unsigned long x;
signed long val;

std::stringstream ss;
ss << std::hex << string_test;
ss >> x;
// ss >> val;  // if I try this val = 0
val = (signed long)x;  // However, if I cast the unsigned result I get val = 0x80123456 

997790cookie-checkC++ konvertiert Hex-String in vorzeichenbehaftete Ganzzahl

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy