programacion - C++ convierte una cadena hexadecimal en un entero con signo
programacion hexadecimal (8)
Andy Buchanan, en lo que respecta a C ++, me gustó el tuyo, pero tengo algunas 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;
}
};
Usado como
uint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");
De esta forma, no necesita una impl por tipo int.
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 formato binario y 10 en decimal.
Aquí hay un método simple y funcional que encontré en otra parte:
string hexString = "7FF";
int hexNumber;
sscanf(hexString.c_str(), "%x", &hexNumber);
Tenga en cuenta que tal vez prefiera usar un entero largo sin signo / entero largo para recibir el valor. Otra nota, la función c_str () simplemente convierte std :: string en const char *.
Entonces, si tiene un const char * listo, simplemente siga usando ese nombre de variable directamente, como se muestra a continuación [También estoy mostrando el uso de la variable larga sin signo para un número hexadecimal más grande. No lo confundas con el caso de tener const char * en lugar 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);
Esto funciona perfectamente bien (siempre que use tipos de datos adecuados según sus necesidades).
El 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 computadora numeric_limits<long>::max()
da 0x7fffffff
. Obviamente, 0xfffefffe
es mayor que 0x7fffffff
. Entonces strtol
devuelve MAX_LONG
lugar del valor deseado. strtoul
convierte la string
en unsigned long
, por eso no hay desbordamiento en este caso.
Ok, strtol
está considerando la cadena de entrada no como un entero de 32 bits con signo antes de la convertación. Muestra divertida con 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;
}
}
El código de arriba imprime -65538
en la consola.
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
Para un método que funciona tanto con C como con C ++, es posible que desee considerar el uso de la función de 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;
}
}
Tuve el mismo problema hoy, así es como 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...
(Encontré esta página cuando estaba buscando una manera menos sucky :-)
Saludos, A.
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;
}
usar std::stringstream
unsigned int x;
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;
el siguiente ejemplo produce -65538
como 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;
}
EDITAR: actualización C ++ 11. En el nuevo estándar, hay algunas nuevas funciones de utilidad que puede utilizar. específicamente, hay una familia de funciones "string to number" ( http://en.cppreference.com/w/cpp/string/basic_string/stol y http://en.cppreference.com/w/cpp/string/basic_string/stoul ). Estas son esencialmente envolturas delgadas para las funciones de conversión de números de C, pero saben cómo manejar una std::string
Por lo tanto, la respuesta más simple para el código más reciente probablemente se vería así:
std::string s = "0xfffefffe";
unsigned int x = std::stoul(s, nullptr, 16);
NOTA: A continuación está mi respuesta original, que como dice la edición no es una respuesta completa. Para una solución funcional. Pon el código encima de la línea :-).
EDITAR: Parece que desde lexical_cast<>
se define tener semántica de conversión de flujo. Lamentablemente, las transmisiones no entienden la notación "0x". Por lo tanto, tanto el boost::lexical_cast
como mi mano rodada no funcionan bien con cadenas hexagonales. La solución anterior que establece manualmente el flujo de entrada a hexadecimal lo manejará bien.
Boost también tiene algunas cosas para hacer esto, que también tiene algunas buenas capacidades de comprobació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 el impulso, aquí hay una versión ligera del elenco léxico que no verifica 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");