代码之家  ›  专栏  ›  技术社区  ›  Clayton

C++将十六进制字符串转换为带符号整数

  •  159
  • Clayton  · 技术社区  · 17 年前

    我想在C++中将十六进制字符串转换为32位有符号整数。

    例如,我有十六进制字符串“fffefffe”。其二进制表示为111111111111111 011111111111110。它的带符号整数表示为:-65538。

    如何在C++中进行此转换?这也需要适用于非负数。例如,十六进制字符串“0000000A”,二进制为00000000000000000000000000001010,十进制为10。

    10 回复  |  直到 17 年前
        1
  •  269
  •   Robert Harvey    7 年前

    使用 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...
    }
    

    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"); 
    
        2
  •  70
  •   Geof Sawaya    13 年前

    对于同时适用于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;
        }
    }
    
        3
  •  27
  •   Mike Lundy    16 年前

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

        4
  •  16
  •   Kirill V. Lyadvinsky    17 年前

    工作示例 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 所以 回报 MAX_LONG 转换 unsigned long 这就是为什么在这种情况下没有溢出。

    好 啊, 在转换之前,正在考虑输入字符串不是32位有符号整数。有趣的样品 甾醇 :

    #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

        5
  •  10
  •   AamodG    14 年前

    以下是我在其他地方发现的一种简单的工作方法:

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

    因此,如果你有一个const char*就绪,只需直接使用该变量名,如下所示[我还展示了无符号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);
    

        6
  •  7
  •   Andy J Buchanan    13 年前

    我今天也遇到了同样的问题,以下是我解决它的方法,这样我就可以保持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...
    

    (当我在寻找一种不那么糟糕的方式时发现了这个页面:-)

    干杯, A.

        7
  •  5
  •   Wang    5 年前

    只需使用stoi/stol/stoll 例如:

    std::cout << std::stol("fffefffe", nullptr, 16) << std::endl;
    

    输出:4294901758

        8
  •  3
  •   mike    15 年前

    这对我奏效了:

    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 
    
        9
  •  3
  •   Johannes Beutel    6 年前

    试试这个。这个解决方案有点冒险。没有支票。字符串只能有十六进制值,字符串长度必须与返回类型大小匹配。但不需要额外的标题。

    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整除

        10
  •  1
  •   justinokamoto    5 年前

    对于那些希望将数基转换为无符号数的人来说,在C/C++中以最小的依赖性自己完成是相当简单的(语言本身没有提供的唯一运算符是 pow()

    用数学术语来说,正序数 在基地 b 随着

    math summation

    00f 看起来像:

    math summation

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