如何使用cout打印0x0a而不是0xa?
#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年)
请查看已经被接受进入C++20的 {fmt}库。基准测试显示它比 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
,那么由于持久性的左/右重定向,你会得到错误的输出结果。必须使用 setfill('0') << setw(2) << right << hex
来始终确保正确对齐。 - fuujuhicout << "0x" << setfill('0') << setw(2) << hex << 10 << endl
- Emile Cormiersetiosflags(ios::internal)
。这个代码可以正常运行:cout << showbase << setiosflags(ios::internal) << setfill('0') << setw(4) << hex << 10 << endl;
示例:http://ideone.com/WlusB - Potatoswatter下面是更新版本,有两种方法可以插入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;
请参见下文详细说明的两个选项:此处可实时查看。
注释:
This line is responsible for showing the base, and can be either of the following:
<< "0x"
<< std::showbase
The first option will display improperly for custom types that try to output negative hex numbers as -0x##
instead of as <complement of 0x##>
, with the sign displaying after the base (as 0x-##
) instead of before it. This is very rarely an issue, so I personally prefer this option.
If this is an issue, then when using these types, you can check for negativity before outputting the base, then using abs()
(or a custom abs()
that returns an unsigned value, if you need to be able to handle the most-negative values on a 2's complement system) on val
.
The second option will omit the base when val == 0
, displaying (e.g., for int
, where int
is 32 bits) 0000000000
instead of the expected 0x00000000
. This is due to the showbase
flag being treated like printf()
's #
modifier internally.
If this is an issue, you can check whether val == 0
, and apply special handling when it does.
Depending on which option was chosen for showing the base, two lines will need to be changed.
<< "0x"
, then HEX_BASE_CHARS
is unnecessary, and can be omitted.If using << std::showbase
, then the value supplied to setw()
needs to account for this:
<< 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。 - j4xclimits
、iomanip
、iostream
、types
、string
、stringstream
,其中 climits
中的 CHAR_BIT
引发了我写下这条评论。 - mxmlnknios
而不是iostream
,但这是无关紧要的,因为iostream
必须包含ios
。已在答案中注明。) - Justin Time - Reinstate Monicachar8_t
,并且为了方便起见,将所有字符类型([[un]signed] char
,charN_t
,wchar_t
)视为相同可能也很有用。 在这种情况下,当is_char<T>
为真时,最好将其转换为char_traits<T>::int_type
,因为我们已经使用了<string>
。 [不过,我目前正在等待事情的进展。] - Justin Time - Reinstate Monicastd::format
来实现此功能:std::cout << std::format("{:02x}\n", 10);
输出:
0a
std::format
是基于它的。{fmt}还提供了print
函数,使这一过程更加简便和高效(godbolt):fmt::print("{:02x}\n", 10);
声明:我是{fmt}和C++20 std::format
的作者。
right
:cout<<"0x"<<hex<<setfill('0')<<setw(2)<<right<<10;
std::showbase
而不是直接输出0x
,则应使用std::internal
而不是std::right
。 - Justin Time - Reinstate Monica试试这个...你只需根据数量级在前面添加零。
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;
cout << hex << "0x" << ((c<0x10)?"0":"") << ((c<0x100)?"0":"") << ((c<0x1000)?"0":"") << (static_cast<unsigned int>(c) & 0xFFFF) << "h" << endl;
And so on.. :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
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
/*This should print out 0x0a. The internal adjustment pads the width with the fill character*/
cout << hex << showbase << internal << setfill('0') << setw(4) << 10 << endl;
}
std::cout << "0x0a"
或者std::cout << "0x0A"
都能够满足您的需求。但我猜想您真正想做的是格式化数字。您希望对数字如16、255、256、65536、-1进行怎样的格式化呢? - CB Bailey0
呢?你总是需要0x0
吗,还是你需要字符串的最小长度? - CB Bailey0x0a
是因为你想要最小宽度还是因为你总是想要前导零?除非你的规格说明非常准确,否则你可能得不到想要的答案。 - CB Bailey