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

Ayr*_*osa 51 c++ io iostream iomanip

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

#include  <iostream>

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

int main()  
{  
    cout << hex << showbase << 10 << endl;  
}
Run Code Online (Sandbox Code Playgroud)

Emi*_*ier 85

这适用于GCC:

#include  <iostream>
#include  <iomanip>

using namespace std;

int main()
{
    cout << "0x" << setfill('0') << setw(2) << hex << 10 << endl;
}
Run Code Online (Sandbox Code Playgroud)

如果你厌倦了iostream格式化的怪癖,那么试试Boost.Format吧.它允许使用老式的printf样式格式说明符,但它是类型安全的.

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

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

  • @EmileCornier 抱歉,无意严厉。确实,不完整,但不幸的是可能会导致讨厌的错误。最近,由于持久的 iomanip,我的代码中有两个错误(完全披露:我以前用 C++ 编写了很多代码,但现在不再使用了),这让我认为 C++ iostream 是非常错误的。对于现代语言来说,iostream 使打印最简单的事情变成了一场噩梦。您认为您打印了一个整数,但实际上您以十六进制打印了它。或者,您在输出中得到“0x90”,但实际上该值是 0x09。 (3认同)
  • @fuujuhi *错了*?那就比较严酷了。我想说它是不完整的。还是)感谢你的建议。 (2认同)

Dou*_* T. 20

使用运输及工务局局长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;
}
Run Code Online (Sandbox Code Playgroud)

就个人而言,iostreams的有状态性质总是让我烦恼.我认为提升格式是一个更好的选择,所以我建议另一个答案.

  • 我也得到了0xA.为什么让iostream以你想要的方式格式化东西真是太糟糕了? (4认同)
  • @Charles:对不起,我忘了`setiosflags(ios :: internal)`.这有效:`cout << showbase << setiosflags(ios :: internal)<< setfill('0')<< setw(4)<< hex << 10 << endl;`Demo:http:// ideone. COM/WlusB (3认同)
  • 这对我有用:`cout <<"0x"<< setfill('0')<< setw(2)<< hex << 10 << endl` (2认同)

Jus*_*ica 8

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

更新版本如下; 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();
}
Run Code Online (Sandbox Code Playgroud)

它可以使用如下:

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;
Run Code Online (Sandbox Code Playgroud)

实时:在这里查看两个选项(如脚注中所详述).

脚注:

  1. 此行负责显示基数,可以是以下任一项:

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

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

    • 第二个选项将省略val == 0显示(例如,for int,where int32位)0000000000而不是预期的基数0x00000000.这是因为showbase标志在内部被视为printf()'s #修饰符.

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

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

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

      << std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
      
      Run Code Online (Sandbox Code Playgroud)

原始版本如下:

// 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();
}
Run Code Online (Sandbox Code Playgroud)

然后可以像这样使用:

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;
Run Code Online (Sandbox Code Playgroud)

工作示例:这里.

  • `的std :: internal`!你赢了大奖!这就是我错过的!谢谢@Justin时间. (4认同)

vit*_*aut 6

在 C++20 中,您可以使用std::format以下方法来执行此操作:

std::cout << std::format("{:02x}\n", 10);  
Run Code Online (Sandbox Code Playgroud)

输出:

0a
Run Code Online (Sandbox Code Playgroud)

同时您可以使用基于的{fmt} 库std::format。{fmt} 还提供了print使这变得更容易、更高效的函数 ( godbolt ):

fmt::print("{:02x}\n", 10); 
Run Code Online (Sandbox Code Playgroud)

免责声明:我是 {fmt} 和 C++20 的作者std::format