【问题标题】:Integer to hex string in C++C ++中的整数到十六进制字符串
【发布时间】:2011-07-03 07:27:50
【问题描述】:

如何将C++ 中的整数转换为十六进制字符串?

我可以找到一些方法来做到这一点,但它们似乎主要针对 C。在 C++ 中似乎没有本地方法可以做到这一点。这是一个非常简单的问题;我有一个int,我想将其转换为十六进制字符串以供以后打印。

【问题讨论】:

    标签: c++ decimal hex int


    【解决方案1】:

    使用<iomanip>std::hex。打印的话就发给std::cout,不行就发std::stringstream

    std::stringstream stream;
    stream << std::hex << your_int;
    std::string result( stream.str() );
    

    您可以在第一个 &lt;&lt; 前面加上 &lt;&lt; "0x" 或任何您喜欢的内容。

    其他感兴趣的操作是std::oct(八进制)和std::dec(返回十进制)。

    您可能遇到的一个问题是,这会产生表示它所需的确切数字数量。您可以使用setfillsetw 来规避问题:

    stream << std::setfill ('0') << std::setw(sizeof(your_type)*2) 
           << std::hex << your_int;
    

    所以最后,我建议这样一个函数:

    template< typename T >
    std::string int_to_hex( T i )
    {
      std::stringstream stream;
      stream << "0x" 
             << std::setfill ('0') << std::setw(sizeof(T)*2) 
             << std::hex << i;
      return stream.str();
    }
    

    【讨论】:

    • @MSalters - 恰恰相反。在int 类型上测试您的建议;)
    • @LexFridman,根据需要准确地发出十六进制数字的数量。如果类型是 uint8_t,为什么要发出 8 位数字?
    • 警告:这不适用于单字节,因为 char 总是被威胁为 char
    • 你还需要#include
    • 如果我正在格式化多个int,似乎std::setw需要为每个int输出到流中,而std::hexstd::setfillstd::uppercase,...只需要一次发送到输出流。这似乎不一致?
    【解决方案2】:

    只需将其打印为十六进制数:

    int i = /* ... */;
    std::cout << std::hex << i;
    

    【讨论】:

    • 我会使用std::cout&lt;&lt;std::hex&lt;&lt;i&lt;&lt;std::dec;,否则以后流出的所有整数都将是十六进制的。对于使用 stringstream 的其他答案,您不需要这样做,因为流在​​使用后被丢弃,但 cout 永远存在。
    【解决方案3】:
    int num = 30;
    std::cout << std::hex << num << endl; // This should give you hexa- decimal of 30
    

    【讨论】:

      【解决方案4】:

      使用std::stringstream 将整数转换为字符串,并使用其特殊操作符设置基数。比如这样:

      std::stringstream sstream;
      sstream << std::hex << my_integer;
      std::string result = sstream.str();
      

      【讨论】:

        【解决方案5】:

        您可以尝试以下方法。它正在工作......

        #include <iostream>
        #include <fstream>
        #include <string>
        #include <sstream>
        using namespace std;
        
        template <class T>
        string to_string(T t, ios_base & (*f)(ios_base&))
        {
          ostringstream oss;
          oss << f << t;
          return oss.str();
        }
        
        int main ()
        {
          cout<<to_string<long>(123456, hex)<<endl;
          system("PAUSE");
          return 0;
        }
        

        【讨论】:

        • 一个不错的答案,但请注意 to_string 是 C++11 中命名空间 std 的一部分
        • @Alex 是的,毕竟是 2014 年......天堂禁止我们很快就要开始处理 C++14。
        【解决方案6】:

        对于那些发现许多/大部分 ios::fmtflags 不能与 std::stringstream 一起使用但喜欢 Kornel 早先发布的模板想法的人来说,以下工作有效且相对干净:

        #include <iomanip>
        #include <sstream>
        
        
        template< typename T >
        std::string hexify(T i)
        {
            std::stringbuf buf;
            std::ostream os(&buf);
        
        
            os << "0x" << std::setfill('0') << std::setw(sizeof(T) * 2)
               << std::hex << i;
        
            return buf.str().c_str();
        }
        
        
        int someNumber = 314159265;
        std::string hexified = hexify< int >(someNumber);
        

        【讨论】:

        • 你不应该直接返回 buf.str() 吗?
        【解决方案7】:

        为了让它更轻更快,我建议使用直接填充字符串。

        template <typename I> std::string n2hexstr(I w, size_t hex_len = sizeof(I)<<1) {
            static const char* digits = "0123456789ABCDEF";
            std::string rc(hex_len,'0');
            for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
                rc[i] = digits[(w>>j) & 0x0f];
            return rc;
        }
        

        【讨论】:

        • 这适用于任何类型吗?我的意思也是双,浮点数,uint8_t?
        • @S.R 它适用于整型,不适用于doublefloat(不适用于指针)
        • ...一个非常实用(但有效)的 C 和 C++ 组合,我不确定速度...对于my taste,它有点密集。
        • 谢谢你,精彩的回答。引入流库“只是”这样做似乎很浪费。
        • 这为0xFFFF 打印0000FFFF。我更喜欢将0xFFFF 作为输出。
        【解决方案8】:

        供您参考的代码:

        #include <iomanip>
        #include <sstream>
        ...
        string intToHexString(int intValue) {
        
            string hexStr;
        
            /// integer value to hex-string
            std::stringstream sstream;
            sstream << "0x"
                    << std::setfill ('0') << std::setw(2)
            << std::hex << (int)intValue;
        
            hexStr= sstream.str();
            sstream.clear();    //clears out the stream-string
        
            return hexStr;
        }
        

        【讨论】:

        • 这并没有真正添加到现有的答案中,明确地 clearsstream 毫无意义(无论如何,当函数在下一行返回时它将被销毁)。您可以完全避免使用命名为 hexStrreturn sstream.str(); 而不使用 clearing 并获得相同的效果,将四行代码减少到一行。
        • 当论坛的目的是了解事物和用法时。冗长比节省行数要提供清晰的画面要好得多。问题不在优化代码上,而 answer 试图给出一种处理这种转换的模块化方法。 @ShadowRanger
        • sstream.clear(); 的目的是什么? sstream 对象在作用域结束时自动销毁,所以 return sstream.str(); 会这样做。
        • sstream.clear 将在流以范围结束结束之前清除内容(以清除任何失败和 eof 标志)。实际上,当作用域死亡时,流变量的生命周期,因此sstream.str 可以用于按值返回。 [参考:cplusplus.com/reference/ios/ios/clear/]
        【解决方案9】:

        我愿意:

        int hex = 10;      
        std::string hexstring = stringFormat("%X", hex);  
        

        查看来自 iFreilicht 的 SO 答案和此处所需的模板头文件 GIST

        【讨论】:

          【解决方案10】:

          看看我的解决方案,[1] 我逐字逐句[2] 从我的项目中复制。我的目标是在我的实际需求中结合灵活性和安全性:[3]

          • 没有0x前缀:调用者可以决定
          • 自动宽度扣除:少打字
          • 显式宽度控件:扩大格式,(无损)缩小以节省空间
          • 能够处理long long
          • 仅限于整数类型:通过静默转换避免意外
          • 易于理解
          • 没有硬编码限制
          #include <string>
          #include <sstream>
          #include <iomanip>
          
          /// Convert integer value `val` to text in hexadecimal format.
          /// The minimum width is padded with leading zeros; if not 
          /// specified, this `width` is derived from the type of the 
          /// argument. Function suitable from char to long long.
          /// Pointers, floating point values, etc. are not supported; 
          /// passing them will result in an (intentional!) compiler error.
          /// Basics from: http://stackoverflow.com/a/5100745/2932052
          template <typename T>
          inline std::string int_to_hex(T val, size_t width=sizeof(T)*2)
          {
              std::stringstream ss;
              ss << std::setfill('0') << std::setw(width) << std::hex << (val|0);
              return ss.str();
          }
          

          [1] 基于 Kornel Kisielewicz 的回答
          [2] 只有德语 API 文档被翻译成英语。
          [3] 翻译成CppTest的语言,是这样写的:

          TEST_ASSERT(int_to_hex(char(0x12)) == "12");
          TEST_ASSERT(int_to_hex(short(0x1234)) == "1234");
          TEST_ASSERT(int_to_hex(long(0x12345678)) == "12345678");
          TEST_ASSERT(int_to_hex((long long)(0x123456789abcdef0)) == "123456789abcdef0");
          TEST_ASSERT(int_to_hex(0x123, 1) == "123");
          TEST_ASSERT(int_to_hex(0x123, 8) == "00000123");
          // width deduction test as suggested by Lightness Races in Orbit:
          TEST_ASSERT(int_to_hex(short(0x12)) == "0012");
          

          【讨论】:

          • 可以显示宽度扣除,例如TEST_ASSERT(int_to_hex(short(0x12)) == "0012");
          【解决方案11】:

          感谢林肯在下面的评论,我改变了这个答案。

          以下答案在编译时正确处理 8 位整数。但是,它确实需要 C++17。如果您没有 C++17,则必须执行其他操作(例如,提供此函数的重载,一个用于 uint8_t,一个用于 int8_t,或者使用“if constexpr”之外的其他内容,可能是 enable_if)。

          template< typename T >
          std::string int_to_hex( T i )
          {
              // Ensure this function is called with a template parameter that makes sense. Note: static_assert is only available in C++11 and higher.
              static_assert(std::is_integral<T>::value, "Template argument 'T' must be a fundamental integer type (e.g. int, short, etc..).");
          
              std::stringstream stream;
              stream << "0x" << std::setfill ('0') << std::setw(sizeof(T)*2) << std::hex;
          
              // If T is an 8-bit integer type (e.g. uint8_t or int8_t) it will be 
              // treated as an ASCII code, giving the wrong result. So we use C++17's
              // "if constexpr" to have the compiler decides at compile-time if it's 
              // converting an 8-bit int or not.
              if constexpr (std::is_same_v<std::uint8_t, T>)
              {        
                  // Unsigned 8-bit unsigned int type. Cast to int (thanks Lincoln) to 
                  // avoid ASCII code interpretation of the int. The number of hex digits 
                  // in the  returned string will still be two, which is correct for 8 bits, 
                  // because of the 'sizeof(T)' above.
                  stream << static_cast<int>(i);
              }        
              else if (std::is_same_v<std::int8_t, T>)
              {
                  // For 8-bit signed int, same as above, except we must first cast to unsigned 
                  // int, because values above 127d (0x7f) in the int will cause further issues.
                  // if we cast directly to int.
                  stream << static_cast<int>(static_cast<uint8_t>(i));
              }
              else
              {
                  // No cast needed for ints wider than 8 bits.
                  stream << i;
              }
          
              return stream.str();
          }
          

          原始答案没有像我想象的那样正确处理 8 位整数:

          Kornel Kisielewicz 的回答很棒。但稍加添加有助于捕获使用没有意义的模板参数(例如 float)或会导致混乱的编译器错误(例如用户定义的类型)调用此函数的情况。

          template< typename T >
          std::string int_to_hex( T i )
          {
            // Ensure this function is called with a template parameter that makes sense. Note: static_assert is only available in C++11 and higher.
            static_assert(std::is_integral<T>::value, "Template argument 'T' must be a fundamental integer type (e.g. int, short, etc..).");
          
            std::stringstream stream;
            stream << "0x" 
                   << std::setfill ('0') << std::setw(sizeof(T)*2) 
                   << std::hex << i;
          
                   // Optional: replace above line with this to handle 8-bit integers.
                   // << std::hex << std::to_string(i);
          
            return stream.str();
          }
          

          我已经编辑了这个以添加对 std::to_string 的调用,因为 8 位整数类型(例如 std::uint8_t 传递的值)到 std::stringstream 被视为 char,它不会给你想要的结果.将这些整数传递给std::to_string 可以正确处理它们,并且在使用其他更大的整数类型时不会造成伤害。当然,在这些情况下您可能会受到轻微的性能影响,因为 std::to_string 调用是不必要的。

          注意:我会在原始答案的评论中添加此内容,但我没有代表发表评论。

          【讨论】:

          • 在我的测试中 std::to_string(i) 不会将 std::uint8_t 整数打印为十六进制。我认为这对于 uint8_t 和 int8_t 类型可能必须有单独的条件,因为它们需要转换为更大的整数。
          • @Lincoln 你是对的。我不知道当时(几个月前)我在做什么,这让我的 to_string 处理了 8 位整数。我什至回到了我认为我当时使用的编译器版本,只是为了仔细检查,但 to_string 并没有像我说的那样工作。那么谁知道呢?无论如何,感谢您发现这一点 - 我已经编辑了应该正常工作的答案。
          • 这对于char 仍然会出人意料地工作(这与大多数实现中的uint8_tint8_t 不同(它们分别是unsigned charsigned char))。跨度>
          • @ruslan 是的,bool 和宽字符类型也都匹配 std::is_integral 并且不会使断言失败。但是,由于 char 根据标准是保证唯一的类型,宽 char 类型也是如此,如果需要,您可以处理所有它们(例外是 un/signed char,它匹配任何宽度的 un/signed 整数类型 a byte 在当前机器上 - 通常是 int8 - 如果你想匹配相同宽度的整数,则无法过滤)。您可以通过向 static_assert 添加更多术语来拒绝字符、宽字符、布尔值:... &amp;&amp; !std::is_same_v&lt;char, T&gt; &amp;&amp; !std::is_same_v&lt;bool, T&gt; 等...
          【解决方案12】:
          #include <boost/format.hpp>
          ...
          cout << (boost::format("%x") % 1234).str();  // output is: 4d2
          

          【讨论】:

          • 头文件为#include &lt;boost/format.hpp&gt;
          • Boost 没有预装,这就是原因
          【解决方案13】:
          int var = 20;
          cout <<                          &var << endl;
          cout <<                     (int)&var << endl;
          cout << std::hex << "0x" << (int)&var << endl << std::dec; // output in hex, reset back to dec
          

          0x69fec4(地址)
          6946500(地址到 12 月)
          0x69fec4(十进制地址,十六进制输出)


          本能地接受了这个......
          int 地址 = (int)&var;

          在别处看到这个...
          无符号长地址 = reinterpret_cast(&var);

          评论告诉我这是正确的...
          int 地址 = (int)&var;

          speaking of well covered 轻盈,你在哪里?他们的赞太多了!

          【讨论】:

          • 这个问题已经很详细了;您的回答对已经发布的内容有何补充?地址与它有什么关系?
          • @LightnessRacesinOrbit 它还没有关闭,是吗?你是对最后三个评论的人这么说的吗?这对于我正在寻找的东西来说更加重要。它可能会帮助别人。地址与它有什么关系?谁读取十进制地址?这是一个真实的例子。
          • 发布几乎九年前已经发布的相同答案被认为没有用,并且这种指向等式的指针的引入似乎是突然出现的 - OP 不会询问指针.此外,不,不是unsigned long,而是std::intptr_t
          • intptr_t = int... uintptr_t = unsigned int... 内存地址现在有符号了吗?一个 int 给你多少内存?
          • 你没有抓住重点。 intptr_t 可以存储构建平台上的任何指针; unsigned int 并非 [必然] 如此。而且,这些都与问题无关。我没有进一步的回应
          【解决方案14】:

          我的解决方案。只允许整数类型。

          你可以在https://replit.com/@JomaCorpFX/ToHex上测试/运行

          更新。您可以在第二个参数中设置可选的前缀 0x。

          definition.h

          #include  <iomanip>
          #include <sstream>
          
          template <class T, class T2 = typename std::enable_if<std::is_integral<T>::value>::type>
          static std::string ToHex(const T & data, bool addPrefix = true);
          
          
          
          template<class T, class>
          inline std::string ToHex(const T & data, bool addPrefix)
          {
              std::stringstream sstream;
              sstream << std::hex;
              std::string ret;
              if (typeid(T) == typeid(char) || typeid(T) == typeid(unsigned char) || sizeof(T)==1)
              {
                  sstream << static_cast<int>(data);
                  ret = sstream.str();
                  if (ret.length() > 2)
                  {
                      ret = ret.substr(ret.length() - 2, 2);
                  }
              }
              else
              {
                  sstream << data;
                  ret = sstream.str();
              }
              return (addPrefix ? u8"0x" : u8"") + ret;
          }
          

          ma​​in.cpp

          #include <iostream>
          #include "definition.h"
          
          int main()
          {
              std::cout << ToHex<unsigned char>(254) << std::endl;
              std::cout << ToHex<char>(-2) << std::endl;
              std::cout << ToHex<int>(-2) << std::endl;
              std::cout << ToHex<long long>(-2) << std::endl;
              
              std::cout<< std::endl;
              std::cout << ToHex<unsigned char>(254, false) << std::endl;
              std::cout << ToHex<char>(-2, false) << std::endl;
              std::cout << ToHex<int>(-2, false) << std::endl;
              std::cout << ToHex<long long>(-2, false) << std::endl;
              return 0;
          }
          

          结果:

          0xfe
          0xfe
          0xfffffffe
          0xfffffffffffffffe
          
          fe
          fe
          fffffffe
          fffffffffffffffe
          

          【讨论】:

            【解决方案15】:

            我想添加一个答案来享受C ++语言的美丽。其对高低工作的适应性。快乐编程。

            public:template <class T,class U> U* Int2Hex(T lnumber, U* buffer)
            {
                const char* ref = "0123456789ABCDEF";
                T hNibbles = (lnumber >> 4);
            
                unsigned char* b_lNibbles = (unsigned char*)&lnumber;
                unsigned char* b_hNibbles = (unsigned char*)&hNibbles;
            
                U* pointer = buffer + (sizeof(lnumber) << 1);
            
                *pointer = 0;
                do {
                    *--pointer = ref[(*b_lNibbles++) & 0xF];
                    *--pointer = ref[(*b_hNibbles++) & 0xF];
                } while (pointer > buffer);
            
                return buffer;
            }
            

            例子:

            char buffer[100] = { 0 };
            Int2Hex(305419896ULL, buffer);//returns "0000000012345678"
            Int2Hex(305419896UL, buffer);//returns "12345678"
            Int2Hex((short)65533, buffer);//returns "FFFD"
            Int2Hex((char)18, buffer);//returns "12"
            
            wchar_t buffer[100] = { 0 };
            Int2Hex(305419896ULL, buffer);//returns L"0000000012345678"
            Int2Hex(305419896UL, buffer);//returns L"12345678"
            Int2Hex((short)65533, buffer);//returns L"FFFD"
            Int2Hex((char)18, buffer);//returns L"12"
            

            【讨论】:

            • 这确实使用了其他答案中没有的一些技术。您能否编辑答案以包括一些关于其工作原理和原因的解释?
            【解决方案16】:
            #include <iostream> 
            #include <sstream>  
            
            int main()
            {
            unsigned int i = 4967295; // random number
            std::string str1, str2;
            unsigned int u1, u2;
            
            std::stringstream ss;
            

            使用空指针:

            // INT to HEX
            ss << (void*)i;       // <- FULL hex address using void pointer
            ss >> str1;          //     giving address value of one given in decimals.
            ss.clear();         // <- Clear bits
            // HEX to INT
            ss << std::hex << str1;   // <- Capitals doesn't matter so no need to do extra here
            ss >> u1;
            ss.clear();
            

            添加0x:

            // INT to HEX with 0x
            ss << "0x" << (void*)i;   // <- Same as above but adding 0x to beginning
            ss >> str2;
            ss.clear();
            // HEX to INT with 0x
            ss << std::hex << str2;   // <- 0x is also understood so need to do extra here
            ss >> u2;
            ss.clear();
            

            输出:

            std::cout << str1 << std::endl; // 004BCB7F
            std::cout << u1 << std::endl;   // 4967295
            std::cout << std::endl;
            std::cout << str2 << std::endl; // 0x004BCB7F
            std::cout << u2 << std::endl;   // 4967295
            
            
            return 0;
            }
            

            【讨论】:

              【解决方案17】:

              对于固定位数,例如 2:

                  static const char* digits = "0123456789ABCDEF";//dec 2 hex digits positional map
                  char value_hex[3];//2 digits + terminator
                  value_hex[0] = digits[(int_value >> 4) & 0x0F]; //move of 4 bit, that is an HEX digit, and take 4 lower. for higher digits use multiple of 4
                  value_hex[1] = digits[int_value & 0x0F]; //no need to move the lower digit
                  value_hex[2] = '\0'; //terminator
              

              您还可以编写一个 for 循环变体来处理可变数字量

              好处:

              • 速度:它是最小的位操作,无需外部函数调用
              • 内存:它使用本地字符串,不分配函数堆栈帧,不需要释放内存。无论如何,如果需要,您可以使用字段或全局变量来使 value_ex 保持在堆栈帧之外

              【讨论】:

                【解决方案18】:

                _itoa_s

                char buf[_MAX_U64TOSTR_BASE2_COUNT];
                _itoa_s(10, buf, _countof(buf), 16);
                printf("%s\n", buf);    // a
                

                swprintf_s

                uint8_t x = 10;
                wchar_t buf[_MAX_ITOSTR_BASE16_COUNT];
                swprintf_s(buf, L"%02X", x);
                

                【讨论】:

                  【解决方案19】:

                  char_to_hex 返回一个由两个字符组成的字符串

                  const char HEX_MAP[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
                  
                  char replace(unsigned char c)
                  {
                      return HEX_MAP[c & 0x0f];
                  }
                  
                  std::string char_to_hex(unsigned char c)
                  {
                      std::string hex;
                  
                      // First four bytes
                      char left = (c >> 4);
                      // Second four bytes
                      char right = (c & 0x0f);
                  
                      hex += replace(left);
                      hex += replace(right);
                  
                      return hex;
                  } 
                  

                  【讨论】:

                    【解决方案20】:

                    从 C++20 开始,使用 std::format,您可能会这样做:

                    std::format("{:#x}", your_int);    // 0x2a
                    std::format("{:#010x}", your_int); // 0x0000002a
                    

                    Demo

                    【讨论】:

                      【解决方案21】:

                      你可以用 C++20 std::format:

                      std::string s = std::format("{:x}", 42); // s == 2a
                      

                      std::format 广泛可用之前,您可以使用the {fmt} librarystd::format 基于 (godbolt):

                      std::string s = fmt::format("{:x}", 42); // s == 2a
                      

                      免责声明:我是 {fmt} 和 C++20 std::format 的作者。

                      【讨论】:

                        【解决方案22】:

                        您可以像这样定义 MACRO 以用作一个衬垫。

                        #include <sstream>
                        #define to_hex_str(hex_val) (static_cast<std::stringstream const&>(std::stringstream() << "0x" << std::hex << hex_val)).str()
                        

                        【讨论】:

                          猜你喜欢
                          • 2013-04-28
                          • 2017-08-12
                          • 2017-08-07
                          • 1970-01-01
                          • 2013-10-22
                          • 2012-01-24
                          • 2010-10-04
                          • 2011-06-15
                          • 2018-03-21
                          相关资源
                          最近更新 更多