C++ 如何使用 cout 打印 0x0a 而不是 0xa?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5760252/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:49:27  来源:igfitidea点击:

How can I print 0x0a instead of 0xa using cout?

c++ioiostreamiomanip

提问by Ayrosa

How can I print 0x0a, instead of 0xa using cout?

如何使用 cout 打印 0x0a 而不是 0xa?

#include  <iostream>

using std::cout;  
using std::endl;  
using std::hex;

int main()  
{  
    cout << hex << showbase << 10 << endl;  
}

回答by Emile Cormier

This works for me in GCC:

这在 GCC 中对我有用:

#include  <iostream>
#include  <iomanip>

using namespace std;

int main()
{
    cout << "0x" << setfill('0') << setw(2) << right << hex << 10 << endl;
}


If you are getting sick and tired of iostream's formatting quirkiness, give Boost.Formata try. It allows good-old-fashioned, printf-style format specifiers, yet it is type-safe.

如果您对 iostream 的格式化怪癖感到厌烦,请尝试Boost.Format。它允许使用老式的 printf 风格的格式说明符,但它是类型安全的。

#include <iostream>
#include <boost/format.hpp>

int main()
{
    std::cout << boost::format("0x%02x\n") % 10;
}


UPDATE (2019)

更新 (2019)

Check out the {fmt} librarythat's been accepted into C++20. Benchmarks show it to be faster than Boost.Format.

查看已被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);

回答by Doug T.

Use setwand setfillfrom iomanip

使用运输及工务局局长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;
}

Personally, the stateful nature of iostreams always annoys me. I think boost format is a better option, so I'd recommended the other answer.

就个人而言,iostream 的状态特性总是让我烦恼。我认为 boost 格式是一个更好的选择,所以我推荐了另一个答案。

回答by Justin Time - Reinstate Monica

If you want to make an easier way to output a hex number, you could write a function like this:

如果您想以更简单的方式输出十六进制数,您可以编写如下函数:

Updated version is presented below; there are two ways the 0xbase indicator can be inserted, with footnotes detailing the differences between them. The original version is preserved at the bottom of the answer, so as not to inconvenience anyone that was using it.

更新版本如下;有两种方法0x可以插入基本指示符,脚注详细说明了它们之间的差异。原始版本保留在答案的底部,以免给使用它的人带来不便。

Note that both the updated and original versions may need some tailoring for systems where the byte size is a multiple of 9 bits.

请注意,对于字节大小为 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();
}

It can be used as follows:

它可以按如下方式使用:

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;

See both options (as detailed in footnotes, below) live: here.

查看两个选项(详见下面的脚注) live: here

Footnotes:

脚注:

  1. 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 intis 32 bits) 0000000000instead of the expected 0x00000000. This is due to the showbaseflag 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.

  2. Depending on which option was chosen for showing the base, two lines will need to be changed.

    • If using << "0x", then HEX_BASE_CHARSis 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)
      
  1. 此行负责显示基数,可以是以下任一项:

    << "0x"
    << std::showbase
    
    • 对于尝试输出负十六进制数 as-0x##而不是 as 的自定义类型,第一个选项将显示不正确,<complement of 0x##>符号显示在基数 (as 0x-##) 之后而不是之前。这很少是一个问题,所以我个人更喜欢这个选项。

      如果这是一个问题,那么在使用这些类型时,您可以在输出基数之前检查负值,然后使用abs()(或返回无符号值的自定义abs(),如果您需要能够处理 2 上的最负值补系统)上val

    • 第二个选项将省略 base when val == 0,显示(例如,for int,whereint是 32 位)0000000000而不是预期的0x00000000。这是由于showbase标志在内部被视为printf()#修饰符。

      如果这是一个问题,您可以检查是否存在val == 0,并在出现问题时应用特殊处理。

  2. 根据选择的显示基地的选项,需要更改两行。

    • 如果使用<< "0x",则HEX_BASE_CHARS是不必要的,可以省略。
    • 如果使用<< std::showbase,则提供给的值setw()需要考虑到这一点:

      << std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
      


The original version is as follows:

原始版本如下:

// 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();
}

Which can then be used like this:

然后可以像这样使用:

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;

Working example: here.

工作示例:here

回答by lentz

The important thing that the answer is missing is that you must use rightwith all of the above mentioned flags:

缺少答案的重要一点是您必须使用right上述所有标志:

cout<<"0x"<<hex<<setfill('0')<<setw(2)<<right<<10;

回答by rwhenderson

To shorten things up for outputting hex, I made a simple macro

为了缩短输出十六进制的时间,我做了一个简单的宏

#define PADHEX(width, val) setfill('0') << setw(width) << std::hex << (unsigned)val

then

然后

cout << "0x" << PADHEX(2, num) << endl;

回答by Michael Grieswald

try this.. you simply prepend zeroes based on magnitude.

试试这个..你只需根据大小在前面加上零。

cout << hex << "0x" << ((c<16)?"0":"") << (static_cast<unsigned int>(c) & 0xFF) << "h" << endl;

You can easily modify this to work with larger numbers.

您可以轻松修改它以处理更大的数字。

cout << hex << "0x";
cout << ((c<16)?"0":"") << ((c<256)?"0":"");
cout << (static_cast<unsigned int>(c) & 0xFFF) << "h" << endl;

Factor is 16 (for one hex-digit):
16, 256, 4096, 65536, 1048576, ..
respective
0x10, 0x100, 0x1000, 0x10000, 0x100000, ..

因子是 16(一个十六进制数字):
16, 256, 4096, 65536, 1048576, ..
分别为
0x10, 0x100, 0x1000, 0x10000, 0x100000, ..

Therefore you could also write like this..

所以你也可以这样写..

cout << hex << "0x" << ((c<0x10)?"0":"") << ((c<0x100)?"0":"") << ((c<0x1000)?"0":"") << (static_cast<unsigned int>(c) & 0xFFFF) << "h" << endl;

And so on.. :P

等等.. :P

回答by Danilo Ramos

Print any number to hex with auto-padding '0' or set. Template allows any data type (e.g. uint8_t)

使用自动填充“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); }

Example:

例子:

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();

Output:

输出:

05,5b,30
0x0001,0f,ffffffff,0201,0x010003