C++ преобразование шестнадцатеричной строки в целое число со знаком
Я хочу преобразовать шестнадцатеричную строку в 32-разрядное целое число со знаком в C++.
Так, например, у меня есть шестнадцатеричная строка "fffefffe". Двоичное представление этого является 11111111111111101111111111111110. Целочисленное представление со знаком это: -65538.
Как сделать это преобразование в C++? Это также должно работать для неотрицательных чисел. Например, шестнадцатеричная строка "0000000A", которая является 00000000000000000000000000001010 в двоичном формате и 10 в десятичный.
8 ответов:
использовать
std::stringstreamunsigned 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; }EDIT: обновление C++11. В новом стандарте, есть несколько новых функций, которые вы можете использовать! в частности, существует семейство функций "строка-число" (http://en.cppreference.com/w/cpp/string/basic_string/stol и http://en.cppreference.com/w/cpp/string/basic_string/stoul). это по сути, тонкие обертки вокруг функций преобразования строки C в число, но знают, как обращаться с A
std::stringИтак, самый простой ответ для более нового кода, вероятно, будет выглядеть так:
std::string s = "0xfffefffe"; unsigned int x = std::stoul(s, nullptr, 16);Примечание: Ниже приведен мой оригинальный ответ, который, как говорится в правке, не является полным ответом. Для функционального решения. Вставьте код над строкой : -).
EDIT: похоже, что после
lexical_cast<>определен семантика преобразования потока. К сожалению, потоки не понимают нотацию "0x". Так что обаboost::lexical_castи моя рука свернула один не очень хорошо справляется с шестнадцатеричными строками. Вышеуказанное решение, которое вручную устанавливает входной поток в hex будет обрабатывать это просто отлично.Boost имеет некоторые вещи чтобы сделать это, а также, который имеет некоторые хорошие возможности проверки ошибок, а также. Вы можете использовать его следующим образом:
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");
для метода, который работает как с 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; } }
Энди Бьюкенен, насколько придерживаться C++ идет, мне понравилось твое, но у меня есть несколько модов:
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");таким образом, вам не нужен один impl на тип int.
рабочий пример с
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в консоли.
вот простой и рабочий способ я нашел в другом месте:
string hexString = "7FF"; int hexNumber; sscanf(hexString.c_str(), "%x", &hexNumber);обратите внимание, что вы можете предпочесть использовать unsigned long integer/long integer, чтобы получить значение. Еще одно замечание, функция c_str () просто преобразует std::string в const char* .
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);это работает просто отлично (при условии, что вы используете соответствующие типы данных в соответствии с вашими потребностями).
У меня была та же проблема сегодня, вот как я решил ее, чтобы я мог сохранить 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...(нашли эту страницу, когда я искал менее отстойный путь :-)
Ура, А.
это сработало для меня:
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
другой метод
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; }
Comments