Если вы хотите сделать более простой способ вывода шестнадцатеричного числа, вы можете написать такую функцию:
Обновленная версия представлена ниже;Существует два способа установки базового индикатора 0x
со сносками, детализирующими различия между ними.Исходная версия сохранена в нижней части ответа, чтобы не доставлять неудобств любому, кто ее использовал.
Обратите внимание, что как обновленная, так и исходная версии могут нуждаться в некоторой адаптации для систем, в которыхразмер байта кратен 9 битам.
#include <type_traits> // For integral_constant, is_same.
#include <string> // For string.
#include <sstream> // For stringstream.
#include <ios> // For hex, internal, [optional] showbase.
// Note: <ios> is unnecessary if <iostream> is also included.
#include <iomanip> // For setfill, setw.
#include <climits> // For CHAR_BIT.
namespace detail {
constexpr int HEX_DIGIT_BITS = 4;
//constexpr int HEX_BASE_CHARS = 2; // Optional. See footnote #2.
// Replaced CharCheck with a much simpler trait.
template<typename T> struct is_char
: std::integral_constant<bool,
std::is_same<T, char>::value ||
std::is_same<T, signed char>::value ||
std::is_same<T, unsigned char>::value> {};
}
template<typename T>
std::string hex_out_s(T val) {
using namespace detail;
std::stringstream sformatter;
sformatter << std::hex
<< std::internal
<< "0x" // See footnote #1.
<< std::setfill('0')
<< std::setw(sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) // See footnote #2.
<< (is_char<T>::value ? static_cast<int>(val) : val);
return sformatter.str();
}
Он может использоваться следующим образом:
uint32_t hexU32 = 0x0f;
int hexI = 0x3c;
unsigned short hexUS = 0x12;
std::cout << "uint32_t: " << hex_out_s(hexU32) << '\n'
<< "int: " << hex_out_s(hexI) << '\n'
<< "unsigned short: " << hex_out_s(hexUS) << std::endl;
См. оба варианта (как подробно описано в сносках ниже).: здесь .
Сноски:
Эта строка отвечает за отображение базы и может быть одной из следующих:
<< "0x"
<< std::showbase
Первый параметр будет отображаться неправильно для пользовательских типов, которые пытаются выводить отрицательные шестнадцатеричные числа как -0x##
вместо <complement of 0x##>
, с признаком, отображаемым после основания (как 0x-##
) а не перед этим.Это очень редкая проблема, поэтому я лично предпочитаю эту опцию.
Если это проблема, то при использовании этих типов вы можете проверить негативность перед выводом базы, а затем с помощью abs()
(или пользовательский abs()
, который возвращает значение без знака , если вам нужно обрабатывать наиболее отрицательные значения в системе дополнения 2) в val
.
Второй параметр пропустит базу при val == 0
, отображая (например, для int
, где int
- 32 бита) 0000000000
вместо ожидаемого 0x00000000
.Это связано с тем, что флаг showbase
обрабатывается как модификатор printf()
#
внутри.
Если это проблема, вы можете проверить, есть ли val == 0
, и применить специальную обработкукогда это произойдет.
В зависимости от того, какой вариант был выбран для отображения базы, потребуется изменить две строки.
- Если используется
<< "0x"
, то HEX_BASE_CHARS
не требуется и может быть опущен. Если используется << std::showbase
, то значение, предоставленное setw()
, должно учитывать это:
<< std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
Исходная версия выглядит следующим образом:
// Helper structs and constants for hex_out_s().
namespace hex_out_helper {
constexpr int HEX_DIGIT_BITS = 4; // One hex digit = 4 bits.
constexpr int HEX_BASE_CHARS = 2; // For the "0x".
template<typename T> struct CharCheck {
using type = T;
};
template<> struct CharCheck<signed char> {
using type = char;
};
template<> struct CharCheck<unsigned char> {
using type = char;
};
template<typename T> using CharChecker = typename CharCheck<T>::type;
} // namespace hex_out_helper
template<typename T> std::string hex_out_s(T val) {
using namespace hex_out_helper;
std::stringstream sformatter;
sformatter << std::hex
<< std::internal
<< std::showbase
<< std::setfill('0')
<< std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
<< (std::is_same<CharChecker<T>, char>{} ? static_cast<int>(val) : val);
return sformatter.str();
}
Который затем можно использовать следующим образом:
uint32_t hexU32 = 0x0f;
int hexI = 0x3c;
unsigned short hexUS = 0x12;
std::cout << hex_out_s(hexU32) << std::endl;
std::cout << hex_out_s(hexI) << std::endl;
std::cout << "And let's not forget " << hex_out_s(hexUS) << std::endl;
Рабочий пример: здесь .