C++ 将十六进制字符串转换为有符号整数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1070497/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ convert hex string to signed integer
提问by Clayton
I want to convert a hex string to a 32 bit signed integer in C++.
我想在 C++ 中将十六进制字符串转换为 32 位有符号整数。
So, for example, I have the hex string "fffefffe". The binary representation of this is 11111111111111101111111111111110. The signed integer representation of this is: -65538.
因此,例如,我有十六进制字符串“ffeffeff”。它的二进制表示是 11111111111111101111111111111110。它的有符号整数表示是:-65538。
How do I do this conversion in C++? This also needs to work for non-negative numbers. For example, the hex string "0000000A", which is 00000000000000000000000000001010 in binary, and 10 in decimal.
我如何在 C++ 中进行这种转换?这也需要适用于非负数。例如,十六进制字符串“0000000A”,二进制为00000000000000000000000000001010,十进制为10。
回答by Evan Teran
use std::stringstream
用 std::stringstream
unsigned int x;
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;
the following example produces -65538
as its result:
下面的例子产生-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;
}
In the new C++11 standard, there are a few new utility functions which you can make use of! specifically, there is a family of "string to number" functions (http://en.cppreference.com/w/cpp/string/basic_string/stoland http://en.cppreference.com/w/cpp/string/basic_string/stoul). These are essentially thin wrappers around C's string to number conversion functions, but know how to deal with a std::string
在新的 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
So, the simplest answer for newer code would probably look like this:
因此,较新代码的最简单答案可能如下所示:
std::string s = "0xfffefffe";
unsigned int x = std::stoul(s, nullptr, 16);
NOTE:Below is my original answer, which as the edit says is not a complete answer. For a functional solution, stick the code above the line :-).
注意:以下是我的原始答案,正如编辑所说,这不是一个完整的答案。对于功能性解决方案,将代码粘贴在行上方:-)。
It appears that since lexical_cast<>
is defined to have stream conversion semantics. Sadly, streams don't understand the "0x" notation. So both the boost::lexical_cast
and my hand rolled one don't deal well with hex strings. The above solution which manually sets the input stream to hex will handle it just fine.
似乎既然lexical_cast<>
被定义为具有流转换语义。可悲的是,流不理解“0x”符号。所以boost::lexical_cast
我和我的手都不能很好地处理十六进制字符串。上述手动将输入流设置为十六进制的解决方案可以很好地处理它。
Boost has some stuffto do this as well, which has some nice error checking capabilities as well. You can use it like this:
Boost 也有一些东西可以做到这一点,它也有一些很好的错误检查功能。你可以这样使用它:
try {
unsigned int x = lexical_cast<int>("0x0badc0de");
} catch(bad_lexical_cast &) {
// whatever you want to do...
}
If you don't feel like using boost, here's a light version of lexical cast which does no error checking:
如果您不想使用 boost,这里有一个不进行错误检查的词法转换的精简版:
template<typename T2, typename T1>
inline T2 lexical_cast(const T1 &in) {
T2 out;
std::stringstream ss;
ss << in;
ss >> out;
return out;
}
which you can use like this:
你可以这样使用:
// though this needs the 0x prefix so it knows it is hex
unsigned int x = lexical_cast<unsigned int>("0xdeadbeef");
回答by Clayton
For a method that works with both C and C++, you might want to consider using the standard library function strtol().
对于同时使用 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;
}
}
回答by Mike Lundy
Andy Buchanan, as far as sticking to C++ goes, I liked yours, but I have a few mods:
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;
}
};
Used like
像用过
uint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");
That way you don't need one impl per int type.
这样你就不需要每个 int 类型一个 impl 。
回答by Kirill V. Lyadvinsky
Working example with strtoul
will be:
工作示例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
converts string
to long
. On my computer numeric_limits<long>::max()
gives 0x7fffffff
. Obviously that 0xfffefffe
is greater than 0x7fffffff
. So strtol
returns MAX_LONG
instead of wanted value. strtoul
converts string
to unsigned long
that's why no overflow in this case.
strtol
转换string
为long
. 在我的电脑上numeric_limits<long>::max()
给出0x7fffffff
. 显然0xfffefffe
大于0x7fffffff
。所以strtol
返回MAX_LONG
而不是想要的价值。strtoul
转换string
为unsigned long
这就是为什么在这种情况下没有溢出的原因。
Ok, strtol
is considering input string not as 32-bit signed integer before convertation. Funny sample with strtol
:
好的,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;
}
}
The code above prints -65538
in console.
上面的代码打印-65538
在控制台中。
回答by AamodG
Here's a simple and working method I found elsewhere:
这是我在别处找到的一种简单而有效的方法:
string hexString = "7FF";
int hexNumber;
sscanf(hexString.c_str(), "%x", &hexNumber);
Please note that you might prefer using unsigned long integer/long integer, to receive the value. Another note, the c_str() function just converts the std::string to const char* .
请注意,您可能更喜欢使用无符号长整数/长整数来接收值。另一个注意事项, c_str() 函数只是将 std::string 转换为 const char* 。
So if you have a const char* ready, just go ahead with using that variable name directly, as shown below [I am also showing the usage of the unsigned long variable for a larger hex number. Do not confuse it with the case of having const char* instead of string]:
因此,如果您准备好 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);
This works just perfectly fine (provided you use appropriate data types per your need).
这工作得很好(前提是您根据需要使用适当的数据类型)。
回答by Andy J Buchanan
I had the same problem today, here's how I solved it so I could keep lexical_cast<>
我今天遇到了同样的问题,这是我解决它的方法,所以我可以保留 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...
(Found this page when I was looking for a less sucky way :-)
(当我正在寻找一种不那么糟糕的方式时找到了这个页面:-)
Cheers, A.
干杯,A.
回答by mike
This worked for me:
这对我有用:
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
回答by Johannes Beutel
Try this. This solution is a bit risky. There are no checks. The string must only have hex values and the string length must match the return type size. But no need for extra headers.
尝试这个。这个解决方案有点冒险。没有检查。字符串必须只有十六进制值,并且字符串长度必须与返回类型大小匹配。但不需要额外的标题。
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;
};
Usage:
用法:
int main()
{
char str[4] = {'f','f','f','f'};
std::cout << hextot<int16_t>(str) << "\n";
}
Note: the length of the string must be divisible by 2
注意:字符串的长度必须能被 2 整除