简体   繁体   English

showbase和stringstream的前导零

[英]showbase and leading zero for stringstream

Here is the code: 这是代码:

std::wstringstream wss;    

wss.setf(std::ios_base::hex, std::ios_base::basefield);

wss.setf(std::ios_base::showbase);
// wss << std::showbase;

// wss.width(2);
wss.fill('0');

wss << std::setw(2) << 7;
// wss << std::noshowbase;
wss.unsetf(std::ios_base::showbase);
wss << std::setw(2) << 0;
wss << std::setw(2) << 20;
wss << std::setw(2) << 6;

auto ret = wss.str();

If I set showbase for the stream, I always get below output: 如果我为流设置showbase ,则总是得到以下输出:
0x7001406 , instead of 0x07001406 0x7001406 ,而不是0x07001406

How can I get this zero before 7? 我怎样才能在7之前获得零? I don't want to set the prefix 0x manually like wss << "0x" . 我不想像wss << "0x"那样手动设置前缀0x

Thanks in advance!! 提前致谢!!

Problem is: the prefix is part of the output width! 问题是:前缀是输出宽度的一部分! Try wss << std::setw(4) << 7; 尝试wss << std::setw(4) << 7; for comparison (you now get 00x7 , which still is unwanted...). 进行比较(您现在得到00x7 ,但仍然不需要...)。

Unfortunately, you cannot use precision for integers to get a behaviour equivalent to printf("%#.2x\\n", 7); 不幸的是,您不能对整数使用precision来获得与printf("%#.2x\\n", 7);等效的行为printf("%#.2x\\n", 7); , which obviously is what you intend... ,这显然是您打算的...

My personal variant is having my own converter: 我的个人变体是拥有自己的转换器:

template <typename T>
struct Hex
{
    Hex(T value, size_t width) : value(value), width(width) { }
private:
    T value;
    size_t width;

    template <typename Stream>
    friend Stream& operator<<(Stream& s, Hex h)
    {
        auto fill = s.fill();
        auto flags = s.flags();
        s.fill('0');
        s << "0x" << std::noshowbase << std::hex << std::setw(h.width) << h.value;
        s.fill(fill);
        s.flags(flags);
        return s;

    }
};
template <typename T>
auto hex(T t, size_t width = sizeof(T) * 2) { return Hex<T>(t, width); }

You now can use it as: 您现在可以将其用作:

wss << hex(7, 2);

getting even shorter than having wss << std::setw(2) << 7; 变得比wss << std::setw(2) << 7;更短wss << std::setw(2) << 7; and coming with nice default appropriate to size of the type... 并带有适合该类型大小的默认值...

One minor drawback yet: you need specialisations or overloads for signed and unsigned char, as for these, the character representation ( 0x0s ) is output instead of numerical value ( 0x73 ). 还有一个小缺点:带符号的和无符号的char需要专门化或重载,因为对于这些字符,输出的是字符表示形式( 0x0s )而不是数值( 0x73 )。

auto hex(char t, size_t width = sizeof(char) * 2)
{ return Hex<unsigned int>(t, width); }
auto hex(signed char t, size_t width = sizeof(signed char) * 2)
{ return Hex<signed int>(t, width); }
auto hex(unsigned char t, size_t width = sizeof(unsigned char) * 2)
{ return Hex<unsigned int>(t, width); }

You might replace 2 with CHAR_BIT / 4 in the default, depending on your needs/desires, might cover systems having eg CHAR_BIT == 16 better... 默认情况下,您可以将CHAR_BIT / 4替换为2 ,具体取决于您的需求/愿望,可能覆盖具有CHAR_BIT == 16更好的系统...

Thanks @Aconcagua for your clue! 感谢@Aconcagua的提示!

I think we can use std::ios_base::adjustfield and std::ios_base::internal to do it like this: 我认为我们可以使用std :: ios_base :: adjustfieldstd :: ios_base :: internal来做到这一点:

wss.setf(std::ios_base::hex, std::ios_base::basefield);
int oldFlag = wss.setf(std::ios_base::internal, std::ios_base::adjustfield);

Then 然后

wss.setf(std::ios_base::showbase);
wss.fill('0');

wss << std::setw(4) << 7;
wss.unsetf(std::ios_base::showbase);
//  wss.setf(oldFlag);

wss << std::setw(2) << 0;
wss << std::setw(2) << 20;
wss << std::setw(2) << 6;

Then I get 0x07001406. 然后我得到0x07001406。 Correct me if I cannot do it like this, thanks! 如果我不能这样纠正我,谢谢!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM