在C++中整数到十六进制字符串

kry*_*000 111 c++ int hex decimal

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

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

Kor*_*icz 197

<iomanip>std::hex.如果你打印,只需发送std::cout,如果没有,然后使用std::stringstream

std::stringstream stream;
stream << std::hex << your_int;
std::string result( stream.str() );
Run Code Online (Sandbox Code Playgroud)

你可以在前面加上第一<<<< "0x"或任何你喜欢的,如果你想.

其他感兴趣的方式是std::oct(八进制)和std::dec(回到十进制).

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

stream << std::setfill ('0') << std::setw(sizeof(your_type)*2) 
       << std::hex << your_int;
Run Code Online (Sandbox Code Playgroud)

最后,我建议这样一个功能:

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();
}
Run Code Online (Sandbox Code Playgroud)

  • WARNIG:这不适用于单个字节,因为char始终作为char进行威胁 (14认同)
  • `std :: showbase`将显示一个'0x`前缀... (12认同)
  • @MSalters - 恰恰相反.在`int`类型上测试你的建议;) (7认同)
  • 您还需要#include <sstream> (4认同)
  • @LexFridman,根据需要准确发出十六进制数字的数量.如果类型是uint8_t,为什么会发出8位数? (2认同)
  • 如果我正在格式化多个int,似乎需要将`std :: setw`输出到每个int的流,而`std :: hex`,`std :: setfill`,`std :: uppercase` ,. ..只需要发送到输出流一次.这似乎不一致? (2认同)

vit*_*aut 80

您可以使用 C++20 来做到这一点std::format

std::string s = std::format("{:x}", 42); // s == 2a
Run Code Online (Sandbox Code Playgroud)

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

std::string s = fmt::format("{:x}", 42); // s == 2a
Run Code Online (Sandbox Code Playgroud)

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


And*_*kov 32

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

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;
}
Run Code Online (Sandbox Code Playgroud)


phl*_*psy 22

使用std::stringstream到整数转换成字符串和特殊操作者设置的基础.例如:

std::stringstream sstream;
sstream << std::hex << my_integer;
std::string result = sstream.str();
Run Code Online (Sandbox Code Playgroud)


Eti*_*tel 13

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

int i = /* ... */;
std::cout << std::hex << i;
Run Code Online (Sandbox Code Playgroud)

  • 我会使用`std :: cout &lt;&lt; std :: hex &lt;&lt; i &lt;&lt; std :: dec;`,否则以后流出的所有整数都将为十六进制。对于使用stringstream的其他答案,您不需要这样做,因为流在​​使用后将被丢弃,但是cout可以永远存在。 (2认同)

Jar*_*d42 13

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

std::format("{:#x}", your_int);    // 0x2a
std::format("{:#010x}", your_int); // 0x0000002a
Run Code Online (Sandbox Code Playgroud)

演示


Mah*_*EFE 9

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

#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;
}
Run Code Online (Sandbox Code Playgroud)


s4e*_*eed 9

这个问题很老了,但我很惊讶为什么没有人提到boost::format

cout << (boost::format("%x") % 1234).str();  // output is: 4d2
Run Code Online (Sandbox Code Playgroud)

  • Boost 没有预装,这就是原因 (2认同)

Vio*_*ffe 7

一种新的 C++17 方式:std::to_chars来自<charconv>( https://en.cppreference.com/w/cpp/utility/to_chars ):

char addressStr[20] = { 0 };
std::to_chars(std::begin(addressStr), std::end(addressStr), address, 16);
return std::string{addressStr};
Run Code Online (Sandbox Code Playgroud)

这有点冗长,因为std::to_chars使用预分配的缓冲区来避免动态分配,但这也可以让您优化代码,因为如果处于热点,分配会变得非常昂贵。

对于额外的优化,您可以省略预初始化缓冲区并检查返回值to_chars以检查错误并获取写入数据的长度。注意:to_chars不写空终止符!


Wol*_*olf 6

看看我的解决方案,[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();
}
Run Code Online (Sandbox Code Playgroud)

[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");
Run Code Online (Sandbox Code Playgroud)


Los*_*ity 5

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

以下答案在编译时正确处理 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();
}
Run Code Online (Sandbox Code Playgroud)

没有像我认为的那样正确处理 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();
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 对于“char”(在大多数实现中,它与“uint8_t”和“int8_t”不同(它们分别是“unsigned char”和“signed char”)),这仍然会出乎意料地起作用。 (2认同)

Gra*_*ham 5

我可以看到其他人用作答案的所有精心设计的编码示例,但是在 C++ 应用程序中简单地使用它并没有什么问题:

    printf ("%04x", num);
Run Code Online (Sandbox Code Playgroud)

对于数字 = 128:

    007f
Run Code Online (Sandbox Code Playgroud)

https://en.wikipedia.org/wiki/Printf_format_string

C++ 实际上是经过扩展的原始 C 语言,因此 C 中的任何内容也是完全有效的 C++。