【问题标题】:How to format flags in c++?如何在 C++ 中格式化标志?
【发布时间】:2013-09-08 20:11:00
【问题描述】:

我知道在 C++ 中,我们可以使用 ios::showbase 之类的状态标志来格式化输出/输入...我知道我们可以将 basefield 的标志设置为 hex、oct、dec 但有 bin 吗?以及如何格式化二进制基域中的整数?

【问题讨论】:

  • 是的,误会了
  • 别担心!我欢迎任何评论

标签: c++


【解决方案1】:

您可以使用bitset<>。例如:

    int x = 1025;
    std::cout << std::bitset<32>(x) << std::endl;

以上将产生输出:

00000000000000000000010000000001

【讨论】:

  • 最后你能解释一下为什么没有 ios::bin 吗?
  • C++ 标准没有强制要求。我认为推测原因对我来说是不明智的。
  • @Jxh 哪个库文件包含bitsetiomanip 的定义给出错误。为什么setbase(2) 不起作用?
  • @AbhishekMane: (1) #include &lt;bitset&gt; (2) setbase() 仅定义为对 8、16 或 10 做出反应。
【解决方案2】:

我意识到许多人对使用std::bitset&lt;N&gt; 打印相关值的方法感到满意。虽然是这样的工作,但我想指出 可以编写一个 bin 操纵器,尽管它有点复杂:你将从 std::num_put&lt;char&gt; 派生并安装一个 std::locale使用相应的方面。下面是这种方法的一个实现。查看底部的函数 print() 以查看“不错”的代码 - 顶部只是使用 std::nun_put&lt;char&gt; 方面来实现。

#include <iostream>
#include <iomanip>
#include <locale>
#include <limits>
#include <iterator>
#include <algorithm>

int bin_index(std::ios_base::xalloc());

struct num_put
    : std::num_put<char>
{
public:
    num_put(std::locale const& chain)
        : d_chain(std::use_facet<std::num_put<char> >(chain)) {
    }
private:
#if __cplusplus == 201103L
    typedef long long          long_forward;
    typedef unsigned long long actual_type;
#else
    typedef unsigned long long_forward;
    typedef unsigned long actual_type;
#endif

    std::num_put<char> const& d_chain;
    typedef std::num_put<char>::iter_type iter_type;
    iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill,
                     long v) const {
        return fmt.iword(bin_index)
            ? this->put(to, fmt, fill, static_cast<long_forward>(v))
            : this->d_chain.put(to, fmt, fill, v);
    }
#if __cplusplus == 201103L
    iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill,
                     long long v) const {
        return fmt.iword(bin_index)
            ? this->put(to, fmt, fill, static_cast<unsigned long long>(v))
            : this->d_chain.put(to, fmt, fill, v);
    }
    iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill,
                     unsigned long v) const {
        return fmt.iword(bin_index)
            ? this->put(to, fmt, fill, static_cast<unsigned long long>(v))
            : this->d_chain.put(to, fmt, fill, v);
    }
#endif
    iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill,
                     actual_type v) const {
        if (fmt.iword(bin_index)) {
            char  bits[std::numeric_limits<actual_type>::digits];
            char* end(bits);
            if (v == 0) {
                *end++ = '0';
            }
            else {
                for (; v; ++end) {
                    *end = "01"[v & 0x1u];
                    v >>= 1;
                }
            }
            std::streamsize show(2 * (bool(fmt.flags()
                                           & std::ios_base::showbase)));
            std::streamsize nofill(show + end - bits < fmt.width()
                                   ? fmt.width() - (show + end - bits)
                                   : 0);
            fmt.width(0);
            if (0 < nofill && (fmt.flags() & std::ios_base::right)) {
                end = std::fill_n(end, nofill, fill);
            }
            if (fmt.flags() & std::ios_base::showbase) {
                *end++ = 'b';
                *end++ = '0';
            }
            if (0 < nofill && (fmt.flags() & std::ios_base::internal)) {
                end = std::fill_n(end, nofill, fill);
            }
            to = std::copy(std::reverse_iterator<char*>(end),
                             std::reverse_iterator<char*>(bits),
                             to);
            if (0 < nofill && (fmt.flags() & std::ios_base::left)) {
                to = std::fill_n(to, nofill, fill);
            }
            return to;
        }
        else {
            return this->d_chain.put(to, fmt, fill, v);
        }
    }
};

std::ostream& bin(std::ostream& out)
{
    if (!dynamic_cast<num_put const*>(
            &std::use_facet<std::num_put<char> >(out.getloc()))) {
        std::locale loc(std::locale(), new num_put(out.getloc()));
        out.imbue(loc);
    }
    out.iword(bin_index) = true;
    return out;
}

std::ostream& nobin(std::ostream& out)
{
    out.iword(bin_index) = false;
    return out;
}

void print(int value)
{
    std::cout << std::right;
    std::cout << nobin << std::setw(8) << value << "="
              << bin << std::right << std::setw(20) << value << "'\n";
    std::cout << nobin << std::setw(8) << value << "="
              << bin << std::internal << std::setw(20) << value << "'\n";
    std::cout << nobin << std::setw(8) << value << "="
              << bin << std::left << std::setw(20) << value << "'\n";
}

int main()
{
    std::cout << std::showbase;
    print(0);
    print(17);
    print(123456);
}

【讨论】:

  • 当我编译这段代码时,我得到了 20 个编译时错误;其中:错误 C2632:“long”后跟“long”是非法的
  • @ProDev7:看来你没有使用 C++11!在这种情况下,事情的结构需要略有不同。一旦我有一个版本,我会立即更新答案......
  • @ProDev7:我已更新代码以使用 C++03 和 C++11 进行编译,并使用 do_put() 的适当覆盖版本(我认为;它没有经过彻底测试)。
【解决方案3】:

您还可以添加自己的流操作器,如下所述:

Custom stream manipulator for streaming integers in any base

【讨论】:

    猜你喜欢
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多