Целое число в шестнадцатеричную строку в C ++ - PullRequest
104 голосов
/ 24 февраля 2011

Как мне преобразовать целое число в шестнадцатеричную строку в C ++ ?

Я могу найти несколько способов сделать это, но они в основном нацелены на C.есть родной способ сделать это в C ++.Это довольно простая проблема;У меня есть int, который я хочу преобразовать в шестнадцатеричную строку для последующей печати.

Ответы [ 15 ]

188 голосов
/ 24 февраля 2011

Используйте <iomanip> s std::hex.Если вы печатаете, просто отправьте его на std::cout, если нет, то используйте std::stringstream

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

. Вы можете добавить первый << с помощью << "0x" или любым другимнапример, если вы хотите.

Другие интересные манипы - это std::oct (восьмеричное) и std::dec (обратно в десятичное число).

Одна проблема, с которой вы можете столкнуться, заключается в том, что это приводит кточное количество цифр, необходимых для его представления.Вы можете использовать setfill и setw, чтобы обойти проблему:

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();
}
32 голосов
/ 31 октября 2015

Чтобы сделать его легче и быстрее, я предлагаю использовать прямое заполнение строки.

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 голосов
/ 24 февраля 2011

Используйте std::stringstream для преобразования целых чисел в строки и специальные манипуляторы для установки базы. Например, вот так:

std::stringstream sstream;
sstream << std::hex << my_integer;
std::string result = sstream.str();
13 голосов
/ 24 февраля 2011

Просто напечатайте это как шестнадцатеричное число:

int i = /* ... */;
std::cout << std::hex << i;
8 голосов
/ 25 июня 2012

Вы можете попробовать следующее.Это работает ...

#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 голосов
/ 20 июня 2018

Этот вопрос старый, но я удивлен, почему никто не упомянул boost::format:

cout << (boost::format("%x") % 1234).str();  // output is: 4d2
4 голосов
/ 24 мая 2018

Благодаря комментарию Линкольна ниже, я изменил этот ответ.

Следующий ответ правильно обрабатывает 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-битные целочисленные значения правильно, как я думал:

Корнел Киселевич отлично ответил. Но небольшое добавление помогает выявить случаи, когда вы вызываете эту функцию с аргументами шаблона, которые не имеют смысла (например, 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 не нужен.

Примечание: я бы просто добавил это в комментарии к исходному ответу, но у меня нет представителя для комментариев.

4 голосов
/ 24 февраля 2011
int num = 30;
std::cout << std::hex << num << endl; // This should give you hexa- decimal of 30
2 голосов
/ 06 февраля 2018

Просто взгляните на мое решение, [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 голосов
/ 18 февраля 2016

Код для вашей справки:

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