我想在C ++中将十六进制字符串转换为32位有符号整数。
因此,例如,我有十六进制字符串“fffefffe”。二进制表示形式为11111111111111101111111111111110。有符号整数表示形式为:-65538。
如何在C ++中进行此转换?这也需要适用于非负数。例如,十六进制字符串“0000000A”,二进制为00000000000000000000000000001010,十进制为10。
答案 0 :(得分:204)
使用std::stringstream
unsigned int x;
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;
以下示例生成-65538
作为结果:
#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;
}
在新的C ++ 11标准中,您可以使用一些新的实用程序功能!具体来说,有一系列“字符串到数字”功能(http://en.cppreference.com/w/cpp/string/basic_string/stol和http://en.cppreference.com/w/cpp/string/basic_string/stoul)。这些基本上是围绕C的字符串到数字转换函数的薄包装器,但知道如何处理std::string
因此,对于较新代码的最简单答案可能如下所示:
std::string s = "0xfffefffe";
unsigned int x = std::stoul(s, nullptr, 16);
注意:以下是我的原始答案,正如编辑所说,这不是一个完整的答案。对于功能性解决方案,请将代码粘贴在以下行上: - )。
似乎因为lexical_cast<>
被定义为具有流转换语义。遗憾的是,流不理解“0x”符号。所以boost::lexical_cast
和我的手卷都不能很好地处理十六进制字符串。手动将输入流设置为十六进制的上述解决方案可以很好地处理它。
Boost has some stuff也可以这样做,它也有一些很好的错误检查功能。您可以像这样使用它:
try {
unsigned int x = lexical_cast<int>("0x0badc0de");
} catch(bad_lexical_cast &) {
// whatever you want to do...
}
如果您不想使用boost,这里是一个轻量级的词法演员版本,不会进行错误检查:
template<typename T2, typename T1>
inline T2 lexical_cast(const T1 &in) {
T2 out;
std::stringstream ss;
ss << in;
ss >> out;
return out;
}
你可以这样使用:
// though this needs the 0x prefix so it knows it is hex
unsigned int x = lexical_cast<unsigned int>("0xdeadbeef");
答案 1 :(得分:56)
对于适用于C和C ++的方法,您可能需要考虑使用标准库函数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;
}
}
答案 2 :(得分:26)
Andy Buchanan,至于坚持使用C ++,我喜欢你的,但我有一些mod:
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;
}
};
像
一样使用uint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");
这样你就不需要每个int类型一个impl。
答案 3 :(得分:15)
strtoul
的工作示例将是:
#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
转换为long
。在我的计算机上numeric_limits<long>::max()
提供0x7fffffff
。显然,0xfffefffe
大于0x7fffffff
。因此strtol
会返回MAX_LONG
而不是所需的值。 strtoul
将string
转换为unsigned long
,这就是为什么在这种情况下没有溢出的原因。
好的,strtol
在转换之前将输入字符串视为32位有符号整数。 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;
}
}
上面的代码在控制台中打印-65538
。
答案 4 :(得分:8)
这是我在其他地方找到的一种简单而有效的方法:
string hexString = "7FF";
int hexNumber;
sscanf(hexString.c_str(), "%x", &hexNumber);
请注意,您可能更喜欢使用无符号长整数/长整数来接收值。 另请注意,c_str()函数只是将std :: string转换为const char *。
因此,如果你有一个const char *就好了,那就直接使用那个变量名,如下所示[我也显示了对于一个更大的十六进制数的unsigned long变量的用法。不要将它与具有const char *而不是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);
这非常合适(假设您根据需要使用适当的数据类型)。
答案 5 :(得分:6)
今天我遇到了同样的问题,这是我如何解决它所以我可以保持lexical_cast&lt;&gt;
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...
(当我寻找一种不那么糟糕的方式时找到这个页面: - )
干杯, 甲
答案 6 :(得分:3)
这对我有用:
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
答案 7 :(得分:1)
只需使用stoi / stol / stoll 例如:
std::cout << std::stol("fffefffe", nullptr, 16) << std::endl;
输出:4294901758
答案 8 :(得分:0)
尝试一下。该解决方案有点冒险。没有检查。该字符串只能具有十六进制值,并且字符串长度必须与返回类型的大小匹配。但是不需要额外的标题。
char hextob(char ch)
{
if (ch >= '0' && ch <= '9') return ch - '0';
if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
return 0;
}
template<typename T>
T hextot(char* hex)
{
T value = 0;
for (size_t i = 0; i < sizeof(T)*2; ++i)
value |= hextob(hex[i]) << (8*sizeof(T)-4*(i+1));
return value;
};
用法:
int main()
{
char str[4] = {'f','f','f','f'};
std::cout << hextot<int16_t>(str) << "\n";
}
注意:字符串的长度必须被2整除
答案 9 :(得分:0)
对于那些希望将数基转换为无符号数的人来说,在 C/C++ 中以最小的依赖性完成自己的工作非常简单(语言本身未提供的唯一运算符是 pow()
函数)。
在数学方面,一个以 b 为基数的正序数 d 和 n 位数可以使用以下方法转换为基数 10:< /p>
示例:转换基数为 16 的数字 00f
如下所示:
= 0*16^2 + 0*16^1 + 16*16^0 = 15
C/C++ 示例:
#include <math.h>
unsigned int to_base10(char *d_str, int len, int base)
{
if (len < 1) {
return 0;
}
char d = d_str[0];
// chars 0-9 = 48-57, chars a-f = 97-102
int val = (d > 57) ? d - ('a' - 10) : d - '0';
int result = val * pow(base, (len - 1));
d_str++; // increment pointer
return result + to_base10(d_str, len - 1, base);
}
int main(int argc, char const *argv[])
{
char n[] = "00f"; // base 16 number of len = 3
printf("%d\n", to_base10(n, 3, 16));
}
答案 10 :(得分:-2)
另一种方法
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;
}