【问题标题】:showbase and leading zero for stringstreamstringstream 的 showbase 和前导零
【发布时间】:2018-07-16 07:53:20
【问题描述】:

代码如下:

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

如果我为流设置showbase,我总是得到低于输出:
0x7001406,而不是0x07001406

我怎样才能在 7 点之前得到这个零?我不想像wss &lt;&lt; "0x" 那样手动设置前缀0x

提前致谢!!

【问题讨论】:

    标签: c++ hex wostringstream


    【解决方案1】:

    感谢@Aconcagua 提供线索!

    我认为我们可以使用 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);
    

    然后

    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;
    

    然后我得到 0x07001406。如果我不能这样做,请纠正我,谢谢!

    【讨论】:

    • 这也很好 - 甚至更好,因为使用 showbaseadjustfield == internal 选择 C++ 标准中定义的默认前缀(不过可以集成到我的解决方案中),并直接使用标志,您可以避免像在我的转换器中那样一直设置和重置它们。请注意,您需要将字符类型转换为更大的整数,以防止打印 ASCII 而不是数字(此外,您需要将前缀长度添加到宽度,但您已经注意到...)。
    【解决方案2】:

    问题是:前缀是输出宽度的一部分!尝试wss &lt;&lt; std::setw(4) &lt;&lt; 7; 进行比较(您现在得到00x7,这仍然是不需要的......)。

    不幸的是,您不能将precision 用于整数以获得与printf("%#.2x\n", 7); 等效的行为,这显然是您想要的......

    我的个人变体是拥有自己的转换器:

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

    您现在可以将其用作:

    wss << hex(7, 2);
    

    比拥有wss &lt;&lt; std::setw(2) &lt;&lt; 7; 还要短,并且带有适合类型大小的漂亮默认值...

    还有一个小缺点:您需要对有符号和无符号字符进行特化或重载,至于这些,输出的是字符表示 (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); }
    

    您可以在默认情况下将 2 替换为 CHAR_BIT / 4,具体取决于您的需要/愿望,可能涵盖具有 e. G。 CHAR_BIT == 16 更好...

    【讨论】:

    • 感谢您的回复@Aconcagua!
    猜你喜欢
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多