Pregunta

Quiero convertir una cadena hexadecimal en un entero con signo de 32 bits en C++.

Entonces, por ejemplo, tengo la cadena hexadecimal "fffefffe".La representación binaria de esto es 11111111111111101111111111111110.La representación entera con signo de esto es:-65538.

¿Cómo hago esta conversión en C++?Esto también debe funcionar para números no negativos.Por ejemplo, la cadena hexadecimal "0000000A", que es 00000000000000000000000000001010 en binario y 10 en decimal.

¿Fue útil?

Solución

usar std::stringstream

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

el siguiente ejemplo produce -65538 como su 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;
}

En el nuevo estándar C++11, hay algunas funciones de utilidad nuevas que puedes utilizar.específicamente, existe una familia de funciones de "cadena a número" (http://en.cppreference.com/w/cpp/string/basic_string/stol y http://en.cppreference.com/w/cpp/string/basic_string/stoul).Estos son esencialmente envoltorios delgados alrededor de las funciones de conversión de cadenas a números de C, pero saben cómo lidiar con un std::string

Entonces, la respuesta más simple para el código más nuevo probablemente se vería así:

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

NOTA: A continuación se muestra mi respuesta original, que, como dice la edición, no es una respuesta completa.Para una solución funcional, pegue el código encima de la línea :-).

Parece que desde lexical_cast<> se define para tener una semántica de conversión de flujo.Lamentablemente, las transmisiones no comprenden la notación "0x".Entonces tanto el boost::lexical_cast y el mío hecho a mano no funciona bien con cadenas hexagonales.La solución anterior que configura manualmente el flujo de entrada en hexadecimal lo manejará bien.

Boost tiene algunas cosas para hacer esto también, que también tiene algunas buenas capacidades de verificación de errores.Puedes usarlo así:

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

Si no tiene ganas de usar boost, aquí tiene una versión ligera de conversión léxica que no realiza verificación de errores:

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

que puedes usar así:

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

Otros consejos

Para un método que funciona tanto con C y C ++, es posible que desee considerar el uso de la función de la biblioteca estándar 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, en lo que se pegue a C ++ va, me ha gustado la suya, pero tengo unas pocas modificaciones:

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

Se utiliza como

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

De esa manera usted no necesita uno impl según el tipo int.

Ejemplo de trabajo con 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 convierte string a long. En mi equipo numeric_limits<long>::max() da 0x7fffffff. Obviamente que 0xfffefffe es mayor que MAX_LONG. Así unsigned long devuelve -65538 en lugar del valor deseado. <=> convierte <=> a <=> por eso hay desbordamiento en este caso.

Ok, <=> está considerando cadena de entrada no como entero con signo de 32 bits antes de convertation. muestra divertida 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;
    }
}

El código anterior imprime <=> en la consola.

Aquí está un método simple y de trabajo he encontrado en otro lugar:

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

Tenga en cuenta que es posible que prefiera utilizar sin firmar entero largo / entero largo, para recibir el valor. Otra nota, el c_str () la función simplemente convierte la std :: string a const char *.

Así que si usted tiene un const char * listo, sólo seguir adelante con el uso de ese nombre de la variable directamente, como se muestra a continuación [También estoy mostrando el uso de la variable de largo sin signo de un número hexadecimal más grande. No se debe confundir con el caso de tener const char * en lugar de cadena]:

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

Esto funciona perfectamente bien (siempre que se utilice tipos de datos apropiados según su necesidad).

Yo tenía el mismo problema hoy en día, aquí es cómo lo resolví para poder mantener 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 cuando yo estaba buscando una manera menos va a trompicones: -)

Cheers, A.

Esto funcionó para mí:

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 

otro 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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top