Frage

Ich mag einen Hex-String in eine 32-Bit-Ganzzahl mit Vorzeichen in C ++ konvertieren.

So zum Beispiel habe ich den Hex-String "fffefffe". Die binäre Darstellung dieser ist 11111111111111101111111111111110. Die vorzeichenbehaftete Ganzzahl-Darstellung davon ist: -65.538.

Wie kann ich tun, um diese Umwandlung in C ++? Dies muss auch für nicht-negative Zahlen arbeiten. Zum Beispiel kann der Hex-String "0000000A", die 00000000000000000000000000001010 binär ist, und 10 in dezimal.

War es hilfreich?

Lösung

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

In dem neuen C ++ 11-Standard, gibt es ein paar neue Utility-Funktionen, die Sie nutzen können! Insbesondere gibt es eine Familie von „String-Nummer“ Funktionen ( http: // en .cppreference.com / w / cav / string / basic_string / STOL und http://en.cppreference.com/w/cpp/string/basic_string/stoul ). Diese sind im Wesentlichen dünner Wrapper um C die Zeichenfolge Anzahl Konvertierungsfunktionen, aber wissen, wie man mit einem std::string beschäftigen

So ist die einfachste Antwort für neueren Code wahrscheinlich würde wie folgt aussehen:

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

Hinweis: Im Folgenden finden Sie meine ursprüngliche Antwort, die wie die Bearbeitung sagt, ist keine vollständige Antwort. Für eine funktionierende Lösung, kleben Sie den Code über der Linie: -).

Es scheint, dass da lexical_cast<> definiert Strom Umwandlung Semantik zu haben. Leider Ströme nicht verstehen, die „0x“ Notation. Also sowohl die boost::lexical_cast und meine Hand gerollt ein beschäftigen sich nicht gut mit Hexstring. Die obige Lösung, die manuell den Eingangsstrom zu hex setzt wird damit umgehen gut.

-Boost hat ein paar Sachen dies zu tun, wie gut, das hat einige nette Fehler Fähigkeiten als auch zu überprüfen. Sie können es wie folgt verwendet werden:

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

Wenn Sie mit boost nicht dem Gefühl, hier ist eine Light-Version von lexikalischem Guss, die tut keine Fehlerprüfung:

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 kann wie folgt verwendet werden:

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

Andere Tipps

Für ein Verfahren, das sowohl mit C und C ++ funktioniert, könnte man mit der Standard-Library-Funktion strtol berücksichtigen will ().

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

Andy Buchanan, bis zu C ++ kleben geht, ich mochte Sie, 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;
    }
};

Gebrauchte wie

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

Auf diese Weise brauchen Sie nicht einen impl pro int-Typen.

Arbeitsbeispiel mit strtoul werden:

#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 wandelt string zu long. Auf meinem Computer numeric_limits<long>::max() gibt 0x7fffffff. Offensichtlich, dass 0xfffefffe größer als 0x7fffffff. So strtol kehrt MAX_LONG statt gewünschten Wert. strtoul wandelt string unsigned long deshalb keinen Überlauf in diesem Fall.

Ok, strtol erwägt Eingabezeichenfolge nicht als 32-Bit-Ganzzahl mit Vorzeichen vor convertation. 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 druckt -65538 in der Konsole.

Hier ist eine einfache und Arbeitsweise ich an anderer Stelle gefunden:

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

Bitte beachten Sie, dass Sie es vorziehen könnten unsigned long integer / long integer verwenden, um den Wert zu erhalten. Noch ein Hinweis, die c_str () Funktion nur wandelt die std :: string zu const char *.

Wenn Sie also ein const char * bereit haben, gehen Sie einfach weiter mit der Verwendung der Variablennamen direkt, wie unten gezeigt [Ich bin auch die Verwendung des unsigned long Variable für eine größere Hex-Zahl zeigt. Nicht zu verwechseln mit dem Fall mit const char * statt 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);

Das funktioniert nur völlig in Ordnung (vorausgesetzt, Sie pro Ihre Notwendigkeit, geeignete Datentypen verwenden).

ich das gleiche Problem heute hatte, hier ist, wie ich es gelöst, so konnte ich halten lexical_cast <>

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 für einen weniger mühsamen Weg suchen: -)

Cheers, A.

Das funktioniert für mich:

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 

eine andere Methode

using namespace System;

template <typename NUM>
NUM hexstr2num(String^ h)
{
    NUM v=0;
    String^ k=L"0123456789ABCDEF";
    short l=h->Length;
    char off;
    h=h->ToUpper();

    if(h->Substring(0,1)!=L"H")
        {if(h->Substring(0,2)==L"0X") off=2;}
    else
        {off=1;}

    if(!off) throw;

    char dx=0;
    for(int i=l;i>off;i--)
        {
            if((dx=k->IndexOf(h->Substring(i-1,1)))>=0)
                {v+=dx<<((l-i)<<2);}
            else
                {throw;}
        }
    return v;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top