C ++ converte sequência hexadecimal para inteiro assinado

Eu quero converter uma seqüência de caracteres hexadecimais para um inteiro assinado de 32 bits em C ++.

Então, por exemplo, eu tenho a string hexadecimal “fffefffe”. A representação binária disso é 11111111111111101111111111111110. A representação de número inteiro assinado é: -65538.

Como faço essa conversão em C ++? Isso também precisa funcionar para números não negativos. Por exemplo, a cadeia hexadecimal “0000000A”, que é 00000000000000000000000000001010 em binário e 10 em decimal.

use std::stringstream

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

o exemplo a seguir produz -65538 como resultado:

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

EDIT: atualização de C ++ 11. No novo padrão, existem algumas novas funções de utilitário que você pode usar! especificamente, há uma família de funções "string para numerar" ( http://en.cppreference.com/w/cpp/string/basic_string/stol e http://en.cppreference.com/w/cpp/string/ basic_string / stoul ). Estes são essencialmente thin wrappers em torno da string de C para numerar funções de conversão, mas sabem como lidar com uma std::string

Então, a resposta mais simples para o código mais recente provavelmente seria assim:

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

NOTA: Abaixo está minha resposta original, que como a edição diz não é uma resposta completa. Para uma solução funcional. Cole o código acima da linha :-).


EDIT: parece que desde lexical_cast<> é definido para ter semântica de conversão de stream. Infelizmente, os streams não entendem a notação "0x". Então, tanto o boost::lexical_cast e minha mão rolou um não lida bem com seqüências hex. A solução acima, que define manualmente o stream de input para hexadecimal, irá lidar com isso bem.

O Boost também tem algumas coisas para fazer isso, o que também tem boas capacidades de verificação de erros. Você pode usá-lo assim:

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

Se você não quiser usar boost, aqui está uma versão light do casting léxico que não faz nenhuma verificação de erros:

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

que você pode usar assim:

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

Para um método que funcione com C e C ++, você pode querer considerar o uso da function de biblioteca padrão strtol ().

 #include  #include  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, no que diz respeito ao C ++, gostei do seu, mas tenho alguns mods:

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

Usado como

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

Dessa forma, você não precisa de um impl por tipo int.

Exemplo de trabalho com strtoul será:

 #include  #include  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 converte string em long . No meu computador numeric_limits::max()0x7fffffff . Obviamente, esse 0xfffefffe é maior que 0x7fffffff . Então, strtol retorna MAX_LONG vez do valor desejado. strtoul converte string para unsigned long que é por isso que não há overflow neste caso.

Ok, strtol está considerando a string de input não como um inteiro assinado de 32 bits antes da conversão. Amostra engraçada com strtol :

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

O código acima imprime -65538 no console.

Aqui está um método simples e funcional que encontrei em outro lugar:

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

Por favor, note que você pode preferir usar inteiro longo sem sinal / inteiro longo, para receber o valor. Outra nota, a function c_str () apenas converte o std :: string para const char *.

Portanto, se você tiver um const char * pronto, basta usar o nome da variável diretamente, conforme mostrado abaixo [Também mostrarei o uso da variável longa não assinada para um número hexadecimal maior. Não confunda com o caso de ter const char * em vez de 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); 

Isso funciona perfeitamente (desde que você use tipos de dados apropriados de acordo com sua necessidade).

Eu tive o mesmo problema hoje, aqui está como eu resolvi isso para que eu pudesse manter o 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( value ); } friend std::istream& operator>>( std::istream& in, int32_from_hex& outValue ) { in >> std::hex >> outvalue.value; } }; uint32 material0 = lexical_cast( "0x4ad" ); uint32 material1 = lexical_cast( "4ad" ); uint32 material2 = lexical_cast( "1197" ); int32 materialX = lexical_cast( "0xfffefffe" ); int32 materialY = lexical_cast( "fffefffe" ); // etc... 

(Encontrei esta página quando estava procurando uma maneira menos sucinta 🙂

Felicidades, A.

Isso funcionou para mim:

 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 

outro método

 using namespace System; template  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< <((li)<<2);} else {throw;} } return v; }