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

问题描述 投票:103回答:15

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

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

c++ decimal hex int
15个回答
188
投票

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

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

如果你愿意,你可以在<<或任何你喜欢的任何地方添加第一个<< "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();
}

2
投票

看看我的解决方案,[1]我从我的项目中逐字复制,因此包含德语是API文档。我的目标是在我的实际需求中结合灵活性和安全性:[2]

  • 没有添加0x前缀:来电者可以决定
  • 自动宽度扣除:减少打字
  • 显式宽度控制:扩展格式化,(无损)收缩以节省空间
  • 有能力处理long long
  • 限制为整数类型:通过静默转换避免意外
  • 易于理解
  • 没有硬编码限制
#include <string>
#include <sstream>
#include <iomanip>

/// Vertextet einen Ganzzahlwert val im Hexadezimalformat.
/// Auf die Minimal-Breite width wird mit führenden Nullen aufgefüllt;
/// falls nicht angegeben, wird diese Breite aus dem Typ des Arguments
/// abgeleitet. Funktion geeignet von char bis long long.
/// Zeiger, Fließkommazahlen u.ä. werden nicht unterstützt, ihre
/// Übergabe führt zu einem (beabsichtigten!) Compilerfehler.
/// Grundlagen aus: 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]翻译成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");
// with deduction test as suggested by Lightness Races in Orbit:
TEST_ASSERT(int_to_hex(short(0x12)) == "0012"); 

2
投票

代码供您参考:

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

1
投票

我做:

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

看看来自iFreilicht的SO答案以及GIST所需的模板头文件!


1
投票

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

更新。您可以在第二个参数中设置可选前缀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 Convert::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;
}

main.cpp中

#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


-1
投票

`

char sw(int num){
   char h[16] = {'0','1','2','3','4','5','6','7','8','9','a','b',' c','d','e','f'};
   return h[num];
}

String to_hexa(int num) {
  int i, j, exp = 0, temp = num;
  String hexa;
  String begin;


  while( temp >= 16 ){
    exp++;
    temp /= 16;
  }

  for ( i = 0; i <= exp; ++i){
    temp = num;
    for ( j = i; j <= exp; ++j){
      if ( j == exp ) hexa += String(sw(temp % 16));
      else temp /= 16;
    }
  }
  begin = "0x";
  for (int i=0; i < 3 - exp; i++){
    begin += "0";
  }  
  return begin + hexa;
}

`


-1
投票
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(地址到dec) 0x69fec4(地址为dec,以十六进制输出)


本能地跟着这个...... int address =(int)&var;

在别处看到这个...... unsigned long address = reinterpret_cast(&var);

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

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


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

21
投票

使用std::stringstream将整数转换为字符串及其特殊操纵器来设置基数。例如:

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

13
投票

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

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

8
投票

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

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

4
投票
int num = 30;
std::cout << std::hex << num << endl; // This should give you hexa- decimal of 30

4
投票

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

cout << (boost::format("%x") % 1234).str();  // output is: 4d2

4
投票

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

以下答案在编译时正确处理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的调用,因为对std::uint8_t的8位整数类型(例如传递的std::stringstream值)被视为char,它不会给你想要的结果。将这样的整数传递给std::to_string可以正确处理它们,并且在使用其他更大的整数类型时不会损害它们。当然,在这些情况下你可能会遇到轻微的性能损失,因为std :: to_string调用是不必要的。

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


2
投票

对于那些发现许多/大多数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);
© www.soinside.com 2019 - 2024. All rights reserved.