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

发布于 2024-11-03 11:47:59 字数 230 浏览 1 评论 0原文

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

#include  <iostream>

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

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

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

#include  <iostream>

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

只想待在家 2024-11-10 11:47:59

这对 GCC 中的我有用:

#include  <iostream>
#include  <iomanip>

using namespace std;

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

如果您厌倦了 iostream 的格式怪异,请给出

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

This works for me in 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.Format a try. It allows good-old-fashioned, printf-style format specifiers, yet it is type-safe.

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

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

UPDATE (2019)

Check out the {fmt} library that's been accepted into C++20. Benchmarks show it to be faster than 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);
尤怨 2024-11-10 11:47:59

使用 setwsetfill 来自 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 的状态特性总是让我烦恼。我认为升压格式是更好的选择,所以我推荐了另一个答案。

Use setw and setfill from 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.

孤者何惧 2024-11-10 11:47:59

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

更新版本如下;有两种方法可以插入 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;

实时查看这两个选项(详见下面的脚注): 这里

脚注:

  1. 该行负责显示基础,可以是以下任意一种:

    <前><代码><< “0x”
    << std::展示库

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

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

    • 第二个选项将在 val == 0 时省略基数,显示(例如,对于 int,其中 int 是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)


原始版本如下:

// 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;

工作示例: 此处

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 0x base 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.

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

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

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 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.

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

    • If using << "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)
      

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.

落日海湾 2024-11-10 11:47:59

在 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 的作者。

In C++20 you'll be able to use std::format to do this:

std::cout << std::format("{:02x}\n", 10);  

Output:

0a

In the meantime you can use the {fmt} library, std::format is based on. {fmt} also provides the print function that makes this even easier and more efficient (godbolt):

fmt::print("{:02x}\n", 10); 

Disclaimer: I'm the author of {fmt} and C++20 std::format.

层林尽染 2024-11-10 11:47:59

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

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

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

cout<<"0x"<<hex<<setfill('0')<<setw(2)<<right<<10;
伴我老 2024-11-10 11:47:59

试试这个..您只需根据幅度预先添加零即可。

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

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, ..

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

旧人 2024-11-10 11:47:59

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

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

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

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;
谜兔 2024-11-10 11:47:59

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

Print any number to hex with auto-padding '0' or set. Template allows any data type (e.g. 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
唐婉 2024-11-10 11:47:59
#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;
}
#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;
}
隱形的亼 2024-11-10 11:47:59

也许不完全是他想要的,但我通常使用类似的东西:

class HexDump
{
    unsigned char const*m_ptr;
    int                 m_len;
public:
    template< typename T >
    HexDump( T const& value )
        :   m_ptr( reinterpret_cast<unsigned char const*>( &value ) )
        ,   m_len( sizeof( T ) )
    {
    }

    friend std::ostream& operator<<( std::ostream& dest, HexDump const& hex )
    {
        auto                outOne = [&dest]( unsigned char one )
            {
                static char const   hexChars[] = "0123456789QBCDEF";
                dest.put( hexChars[one >> 4] );
                dest.put( hexChars[one & 0xF] );
            };
        outOne( *hex.m_ptr );
        for ( unsigned char const* p = hex.m_ptr + 1; p != hex.m_ptr + hex.m_len; ++ p ) {
            dest.put( ' ' );
            outOne( *p );
        }
        return dest;
    }

};

这将在调用它的任何对象中输出每个字节的两位数字,并且不使用(或考虑)任何格式标志 - 我通常使用它来调试,因此将其插入到流中,而不知道当前的格式标志,并且非常强烈地希望不更改它们。

例如,可以轻松修改它以不插入空格;也可以对其进行修改以考虑诸如 std::ios_base::showbase 或 std::ios_base::uppercase 之类的内容。

如果您将其用于调试以外的其他用途,您可能需要将其命名为 AsHex,而不是 HexDump

Perhaps not exactly what he's looking for, but I usually use something like:

class HexDump
{
    unsigned char const*m_ptr;
    int                 m_len;
public:
    template< typename T >
    HexDump( T const& value )
        :   m_ptr( reinterpret_cast<unsigned char const*>( &value ) )
        ,   m_len( sizeof( T ) )
    {
    }

    friend std::ostream& operator<<( std::ostream& dest, HexDump const& hex )
    {
        auto                outOne = [&dest]( unsigned char one )
            {
                static char const   hexChars[] = "0123456789QBCDEF";
                dest.put( hexChars[one >> 4] );
                dest.put( hexChars[one & 0xF] );
            };
        outOne( *hex.m_ptr );
        for ( unsigned char const* p = hex.m_ptr + 1; p != hex.m_ptr + hex.m_len; ++ p ) {
            dest.put( ' ' );
            outOne( *p );
        }
        return dest;
    }

};

This will output two digits per byte in whatever object it is called on, and doesn't use (or consider) any formatting flags -- I usually use this for debugging, and so insert it into streams with no knowledge of the current format flags, and a very strong desire to not change them.

It can easily be modified to not insert spaces, for example; it would also be possible to modify it to take into consideration things like std::ios_base::showbase or std::ios_base::uppercase.

If you're using it for something other than debugging, you might want to call it something like AsHex, rather than HexDump.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文