Как я могу напечатать 0x0a вместо 0xa, используя cout?
#include <iostream>
using std::cout;
using std::endl;
using std::hex;
int main()
{
cout << hex << showbase << 10 << endl;
}
Как я могу напечатать 0x0a вместо 0xa, используя cout?
#include <iostream>
using std::cout;
using std::endl;
using std::hex;
int main()
{
cout << hex << showbase << 10 << endl;
}
Это работает для меня в GCC:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << "0x" << setfill('0') << setw(2) << right << hex << 10 << endl;
}
Если вам надоело странное форматирование iostream, дайте Boost.Format попробуйте. Он позволяет использовать старые добрые спецификаторы формата в стиле printf, но при этом является типобезопасным.
#include <iostream>
#include <boost/format.hpp>
int main()
{
std::cout << boost::format("0x%02x\n") % 10;
}
ОБНОВЛЕНИЕ (2019 г.)
Ознакомьтесь с принятой {fmt} библиотекой в C ++ 20. Тесты показывают, что он быстрее, чем Boost.Format.
#if __has_include(<format>)
#include <format>
using std::format;
#else
#include <fmt/format.h>
using fmt::format;
#endif
std::cout << format("{:#04x}\n", 10);
cout << left << whatever
раньше, вы получите плохой результат из-за постоянного левого / правого iomanip. Он должен быть setfill('0') << setw(2) << right << hex
, чтобы всегда гарантировать правильное выравнивание.
- person fuujuhi; 16.12.2019
Используйте setw и setfill из iomanip
#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;
using std::hex;
int main()
{
cout << "0x" << std::setfill('0') << std::setw(2) << hex << 10 << endl;
}
Лично меня всегда раздражает статическая природа iostreams. Я думаю, что формат ускорения - лучший вариант, поэтому я рекомендовал бы другой ответ.
cout << "0x" << setfill('0') << setw(2) << hex << 10 << endl
- person Emile Cormier; 23.04.2011
setw(2)
, похоже, не очень хорошо работает с showbase
, по крайней мере, в gcc 4.4.3. Может это ошибка в GCC?
- person Emile Cormier; 23.04.2011
cout << showbase << setfill('0') << setw(2) << hex << 10 << endl;
, я все равно получаю 0xa
в GCC.
- person Emile Cormier; 23.04.2011
0xa
уже превышает 2 символа, поэтому setw(2)
ничего не сделает. @Potatoswatter: В этом случае я считаю разумным явное 0x
. setw(4) << hex << setfill('0') << showbase << 10
не даст желаемого эффекта (00xa
!).
- person CB Bailey; 23.04.2011
setiosflags(ios::internal)
. Это работает: cout << showbase << setiosflags(ios::internal) << setfill('0') << setw(4) << hex << 10 << endl;
Демо: ideone.com/WlusB
- person Potatoswatter; 23.04.2011
internal
: добавляет символы заполнения в обозначенную внутреннюю точку в определенном сгенерированном выводе или идентично right
, если такая точка не обозначена. Это либо недооценено, либо указано очень загадочно.
- person CB Bailey; 23.04.2011
<< n
, по крайней мере, так было для меня
- person kraxor; 22.01.2021
Если вы хотите упростить вывод шестнадцатеричного числа, вы можете написать такую функцию:
Обновленная версия представлена ниже; Есть два способа вставить базовый индикатор 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"
, then HEX_BASE_CHARS
is unnecessary, and can be omitted.При использовании << 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;
Рабочий пример: здесь.
std::internal
! Вы выиграли большой приз! Вот чего мне не хватало! Спасибо @Justin Time.
- person j4x; 12.06.2017
climits
, iomanip
, iostream
, types
, string
, stringstream
с настройками для CHAR_BIT
, который заставил меня написать этот комментарий.
- person mxmlnkn; 06.02.2018
ios
вместо iostream
, но это спорно, потому что iostream
в любом случае требуется для включения ios
. Это также отмечено в ответе.)
- person Justin Time - Reinstate Monica; 08.07.2019
char8_t
, и что также может быть полезно, чтобы он обрабатывал все типы символов ([[un]signed] char
, charN_t
, wchar_t
) одинаково для удобства. В этом случае, вероятно, будет лучше привести к char_traits<T>::int_type
, когда is_char<T>
истинно, поскольку мы уже используем <string>
. [В настоящее время я жду, чтобы увидеть, как все будет развиваться, прежде чем это сделать.]
- person Justin Time - Reinstate Monica; 30.09.2019
Важная вещь, на которую отсутствует ответ, заключается в том, что вы должны использовать right
со всеми вышеупомянутыми флагами:
cout<<"0x"<<hex<<setfill('0')<<setw(2)<<right<<10;
std::showbase
вместо прямого вывода 0x
, вы используете std::internal
вместо std::right
.
- person Justin Time - Reinstate Monica; 12.03.2016
В C ++ 20 вы сможете использовать для этого std::format
:
std::cout << std::format("{:02x}\n", 10);
Выход:
0a
А пока вы можете использовать библиотеку {fmt}, на основе std::format
. {fmt} также предоставляет функцию print
, которая делает это еще проще и эффективнее (godbolt):
fmt::print("{:02x}\n", 10);
Заявление об ограничении ответственности: я являюсь автором {fmt} и C ++ 20 std::format
.
попробуйте это .. вы просто добавляете нули в зависимости от величины.
cout << hex << "0x" << ((c<16)?"0":"") << (static_cast<unsigned int>(c) & 0xFF) << "h" << endl;
Вы можете легко изменить это для работы с большими числами.
cout << hex << "0x";
cout << ((c<16)?"0":"") << ((c<256)?"0":"");
cout << (static_cast<unsigned int>(c) & 0xFFF) << "h" << endl;
Коэффициент равен 16 (для одной шестнадцатеричной цифры):
16, 256, 4096, 65536, 1048576, ..
соответственно
0x10, 0x100, 0x1000, 0x10000, 0x100000, ..
Поэтому вы также можете написать так ..
cout << hex << "0x" << ((c<0x10)?"0":"") << ((c<0x100)?"0":"") << ((c<0x1000)?"0":"") << (static_cast<unsigned int>(c) & 0xFFFF) << "h" << endl;
И так далее ..: P
Чтобы сократить вывод в шестнадцатеричном формате, я сделал простой макрос
#define PADHEX(width, val) setfill('0') << setw(width) << std::hex << (unsigned)val
тогда
cout << "0x" << PADHEX(2, num) << endl;
Выведите любое число в шестнадцатеричный формат с автоматическим заполнением «0» или установите. Шаблон допускает любой тип данных (например, uint8_t)
template<typename T, typename baseT=uint32_t> struct tohex_t {
T num_;
uint32_t width_;
bool showbase_;
tohex_t(T num, bool showbase = false, uint32_t width = 0) { num_ = num; showbase_ = showbase; width_ = width; }
friend std::ostream& operator<< (std::ostream& stream, const tohex_t& num) {
uint32_t w;
baseT val;
if (num.showbase_)
stream << "0x";
if (num.width_ == 0) {
w = 0;
val = static_cast<baseT>(num.num_);
do { w += 2; val = val >> 8; } while (val > 0);
}
else {
w = num.width_;
}
stream << std::hex << std::setfill('0') << std::setw(w) << static_cast<baseT>(num.num_);
return stream;
}
};
template<typename T> tohex_t<T> TO_HEX(T const &num, bool showbase = false, uint32_t width = 0) { return tohex_t<T>(num, showbase, width); }
Пример:
std::stringstream sstr;
uint8_t ch = 91;
sstr << TO_HEX(5) << ',' << TO_HEX(ch) << ',' << TO_HEX('0') << std::endl;
sstr << TO_HEX(1, true, 4) << ',' << TO_HEX(15) << ',' << TO_HEX(-1) << ',';
sstr << TO_HEX(513) << ',' << TO_HEX((1 << 16) + 3, true);
std::cout << sstr.str();
Выход:
05,5b,30
0x0001,0f,ffffffff,0201,0x010003
0x0a
, в теле вашего вопроса указано0x0A
. В любом случае явноеstd::cout << "0x0a"
илиstd::cout << "0x0A"
могло бы соответствовать вашим требованиям, но я предполагаю, что вы действительно хотите отформатировать число. Как вы хотите отформатировать (например) 16, 255, 256, 65536, -1? - person CB Bailey   schedule 23.04.20110
? Вы всегда хотите0x0
или вам нужна минимальная длина строки? - person CB Bailey   schedule 23.04.20110x0a
, потому что вам нужна минимальная ширина или потому что вам всегда нужен ведущий ноль? Если вы точно не со своей спецификацией, вы можете не получить желаемых ответов. - person CB Bailey   schedule 23.04.2011