首页 文章

C将hex字符串转换为有符号整数

提问于
浏览
113

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

所以,例如,我有十六进制字符串“fffefffe” . 二进制表示形式为11111111111111101111111111111110 . 其带符号整数表示形式为:-65538 .

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

8 回答

  • 14

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

    EDIT: C 11更新 . 在新标准中,您可以使用一些新的实用功能!具体来说,有一个"string to number"函数族(http://en.cppreference.com/w/cpp/string/basic_string/stolhttp://en.cppreference.com/w/cpp/string/basic_string/stoul) . 这些基本上是围绕C的字符串到数字转换函数的薄包装器,但是知道如何处理 std::string

    因此,对于较新的代码,最简单的答案可能如下所示:

    std::string s = "0xfffefffe";
    unsigned int x = std::stoul(s, nullptr, 16);
    

    NOTE: 以下是我的原始答案,正如编辑所说,这不是一个完整的答案 . 对于功能解决方案 . 将代码粘贴在行上方:-) .


    EDIT: 似乎自 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,这里是一个轻量级的lexical cast,没有错误检查:

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

    对于兼容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;
        }
    }
    
  • 6

    Andy Buchanan,至于坚持C去,我喜欢你的,但我有一些mods:

    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 .

  • 8

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

    strtolstring 转换为 long . 在我的电脑上 numeric_limits<long>::max() 给出 0x7fffffff . 显然 0xfffefffe 大于 0x7fffffff . 所以 strtol 返回 MAX_LONG 而不是想要的值 . strtoulstring 转换为 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 .

  • 54

    这是我在其他地方找到的一种简单而有效的方法:

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

    这非常完美(假设您根据需要使用适当的数据类型) .

  • 26

    我今天遇到了同样的问题,这是我如何解决它所以我可以保持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.

  • -2

    这对我有用:

    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
    
  • 3

    另一种方法

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

相关问题