Domanda

voglio convertire una stringa esadecimale in un numero intero con segno a 32 bit in C ++.

Quindi, per esempio, ho la stringa esadecimale "fffefffe". La rappresentazione binaria di questo è 11111111111111101111111111111110. La rappresentazione intero con segno di questo è: -65.538.

Come faccio a fare questa conversione in C ++? Questo ha anche bisogno di lavorare per i numeri non negativi. Ad esempio, la stringa esadecimale "0000000A", che è 00000000000000000000000000001010 in binario, e 10 in decimale.

È stato utile?

Soluzione

utilizzo std::stringstream

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

seguente esempio produce -65538 come risultato:

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

Nel nuovo standard C ++ 11, ci sono alcune nuove funzioni di utilità che si possono fare uso di! in particolare, v'è una famiglia di "stringa di numeri" funzioni ( http: // it .cppreference.com / w / cpp / string / basic_string / stol e http://en.cppreference.com/w/cpp/string/basic_string/stoul ). Questi sono essenzialmente wrapper sottile intorno stringa di C per le funzioni di conversione numero, ma sanno come trattare con un std::string

Quindi, la risposta più semplice per il codice più recente sarebbe probabilmente simile a questa:

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

Nota: Qui di seguito è la mia risposta originale, che come la modifica dice che non è una risposta completa. Per una soluzione funzionale, attaccare il codice di sopra della linea: -).

Sembra che da quando lexical_cast<> è definito avere la semantica di conversione del flusso. Purtroppo, i flussi non capiscono la notazione "0x". Così sia il boost::lexical_cast e la mia mano rotolato uno non trattare bene con le stringhe esadecimali. La soluzione sopra che imposta manualmente il flusso di ingresso di esagono lo gestirà bene.

Boost ha alcune cose per fare questo come bene, che ha qualche bella il controllo degli errori capacità pure. Si può usare in questo modo:

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

Se non avete voglia di usare il boost, ecco una versione light del cast lessicale che non vengono effettuate verifiche di errore:

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

che può essere utilizzato in questo modo:

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

Altri suggerimenti

Per un metodo che funziona sia con C e C ++, si potrebbe prendere in considerazione l'utilizzo della funzione di libreria standard strtol ().

#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, per quanto attaccare a C ++ va, mi è piaciuto il vostro, ma ho un paio di 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;
    }
};

Utilizzato come

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

In questo modo non è necessario uno impl per ogni tipo int.

esempio Lavorare con strtoul sarà:

#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 string converte in long. Sul mio computer numeric_limits<long>::max()0x7fffffff. Ovviamente questo 0xfffefffe è maggiore di MAX_LONG. Così unsigned long restituisce -65538 posto del valore desiderato. <=> converte <=> a <=> è per questo che non troppo pieno in questo caso.

Ok, <=> sta valutando stringa di input non come numero intero con segno a 32 bit prima convertation. campione divertente con <=>:

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

Il codice sopra stampe <=> in console.

Ecco un metodo semplice e di lavoro ho trovato altrove:

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

Si prega di notare che si potrebbe preferire utilizzare unsigned long / intero lungo intero, a ricevere il valore. Un'altra nota, il c_str () funzione solo converte la std :: string a const char *.

Quindi, se si dispone di un const char * pronto, basta andare avanti con l'utilizzo di quel nome di variabile direttamente, come illustrato di seguito [Sto mostrando anche l'utilizzo della lunga variabili unsigned per un numero esadecimale grande. Da non confondere con il caso di avere const char * invece di stringa]:

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

Questo funziona perfettamente bene (a condizione di utilizzare i tipi di dati appropriati per il vostro bisogno).

Ho avuto lo stesso problema di oggi, ecco come ho risolto così ho potuto mantenere 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...

(Trovato questa pagina quando ero alla ricerca di un modo meno sucky: -)

Saluti, A.

Questo ha funzionato per me:

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 

un altro metodo

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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top