Pergunta

Eu quero converter uma string hexadecimal para um inteiro assinado de 32 bits em C ++.

Assim, por exemplo, eu tenho a string hex "fffefffe". A representação binária este é 11111111111111101111111111111110. a representação inteiro assinado disso é: -65538.

Como posso fazer esta conversão em C ++? Isso também precisa de trabalho para os números não negativos. Por exemplo, a string hex "0000000A", que é 00000000000000000000000000001010 em binário, e 10 em decimal.

Foi útil?

Solução

uso std::stringstream

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

exemplo a seguir produz -65538 como seu resultado:

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

No novo C ++ 11 standard, há algumas novas funções de utilidade que você pode fazer uso de! especificamente, há uma família de "string para o número" funções ( http: // en .cppreference.com / w / CPP / string / basic_string / stol e http://en.cppreference.com/w/cpp/string/basic_string/stoul ). Estes são wrappers essencialmente finas ao redor corda de C para funções de conversão de número, mas sabe como lidar com um std::string

Assim, a resposta mais simples para o código mais recente, provavelmente parecido com este:

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

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

.

Parece que desde lexical_cast<> está definido para ter a semântica de conversão de fluxo. Infelizmente, os fluxos não entendo a notação "0x". Assim, tanto o boost::lexical_cast e minha mão rolou um não lidam bem com cordas hexadecimais. A solução acima, que define manualmente o fluxo de entrada para hex vai lidar com isso muito bem.

impulso tem algum coisas para fazer isso como bem, que tem algumas capacidades de verificação de erro de Nice. Você pode usá-lo como este:

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

Se você não se sente como o uso de impulso, aqui está uma versão light do elenco lexical que não faz verificação de erros:

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

que pode ser usado como este:

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

Outras dicas

Para um método que funciona tanto com C e C ++, você pode querer considerar o uso do strtol função de biblioteca padrão ().

#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, na medida em que adere a C ++ vai, eu gostei sua, mas eu tenho algumas 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;
    }
};

Usado como

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

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

Working exemplo, com strtoul será:

#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 convertidos string para long. No meu computador numeric_limits<long>::max()0x7fffffff. Obviamente que 0xfffefffe é maior do que 0x7fffffff. Então retorna strtol MAX_LONG em vez de valor desejado. strtoul convertidos string para unsigned long é por isso que nenhum estouro neste caso.

Ok, strtol está considerando cadeia de entrada não como 32-bit inteiro assinado antes convertation. amostra engraçado com 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;
    }
}

O código acima imprime -65538 no console.

Aqui está um método simples e trabalhar I encontrados em outros lugares:

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

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

Então, se você tem um const char * pronto, basta ir em frente com usando esse nome variável diretamente, como mostrado abaixo [Eu também estou mostrando o uso da variável unsigned long para um número hexadecimal maior. Não confundir 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 bem (desde que você use tipos de dados apropriados por sua necessidade).

Eu tive o mesmo problema hoje, aqui está como eu resolver isso para que eu pudesse manter 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...

(Encontrado esta página quando eu estava procurando uma maneira menos sucky: -)

Cheers, Um.

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 <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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top