C++ 自定义流操纵器,更改流中的下一个项目

标签 c++ stream

在 C++ 中,要以十六进制打印数字,您可以这样做:

int num = 10;
std::cout << std::hex << num; // => 'a'

我知道我可以创建一个操纵器,它只是像这样向流中添加内容:

std::ostream& windows_feed(std::ostream& out)
{
    out << "\r\n";
    return out;
}

std::cout << "Hello" << windows_feed; // => "Hello\r\n"

但是,我如何创建一个像“hex”一样修改项目以进入流的操纵器?作为一个简单的例子,我将如何在这里创建 plusone 操纵器?:

int num2 = 1;
std::cout << "1 + 1 = " << plusone << num2; // => "1 + 1 = 2"

// note that the value stored in num2 does not change, just its display above.
std::cout << num2; // => "1"

最佳答案

首先,您必须将一些状态存储到每个流中。您可以使用函数 iword 来做到这一点和你传递给它的索引,由 xalloc 给出:

inline int geti() { 
    static int i = ios_base::xalloc();
    return i;
}

ostream& add_one(ostream& os) { os.iword(geti()) = 1; return os; } 
ostream& add_none(ostream& os) { os.iword(geti()) = 0; return os; }

有了它,您就可以在所有流中检索一些状态。现在,您只需连接到相应的输出操作。数字输出由一个方面完成,因为它可能依赖于语言环境。所以你可以这样做

struct my_num_put : num_put<char> {
    iter_type 
    do_put(iter_type s, ios_base& f, char_type fill, long v) const { 
        return num_put<char>::do_put(s, f, fill, v + f.iword(geti())); 
    } 

    iter_type 
    do_put(iter_type s, ios_base& f, char_type fill, unsigned long v) const { 
        return num_put<char>::do_put(s, f, fill, v + f.iword(geti())); 
    } 
}; 

现在,您可以测试这些东西了。

int main() {
    // outputs: 11121011
    cout.imbue(locale(locale(),new my_num_put));
    cout << add_one << 10 << 11 
         << add_none << 10 << 11;
}

如果您只想增加下一个数字,只需在每次调用 do_put 后再次将单词设置为 0

关于C++ 自定义流操纵器,更改流中的下一个项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50493819/

相关文章:

c++ - 是否可以通过非托管 C++/MFC 代码向 SOAP Web 服务发送数据/从 SOAP Web 服务接收数据?

python - 如何使用 name 属性实例化 io.TextIOWrapper 对象?

c# - 你如何从无限字节流中读取 UTF-8 字符 - C#

java - 如何以流式传输方式迭代巨大 XML 中的节点?

c++ - "Use of undeclared identifier ' IntQueue ' "即使它被定义

c++ - 在 C++ 中删除对象

C++ 线程安全队列关闭

c++ - 如何按需显示 shell notifyicon 气球工具提示?

c - c中的匿名流

C# 将 FileStream.WriteLine 转换为 MemoryStream