让std::ostream遇到特殊字符自动识别
make std::ostream automatically ident when encountering special characters
我想要一些工具,使 std::ostream
(或派生的)在遇到特殊字符(或特殊对象)时自动识别。假设特殊字符是 <
和 >
。在这种情况下,以下输入 test0<test1<test2, test3<test4> > >
应产生以下输出:
test0<
test1<
test2,
test3<
test4
>
>
>
如何实现这一点?
std::ostream
? IOStream 设计相当复杂(而且有点慢),所以我明白您为什么会这样想。 ostream
这个名字听起来是个不错的提示,但实际上作用不大。它通过将 std::ostreambuf
和 operator<<
重载绑定在一起来真正起作用。派生的 ostream
类 提供具体的流缓冲区。
您想要的可能是 streambuf
过滤器。您获取底层的 streambuf,并将其用作输出,但是当您看到 >
时,您插入了一些额外的空格
boost::iostreams 使这相当容易,您可以定义过滤器,然后将它们与输出流链接在一起,以将输入转换为所需的输出:
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
namespace io = boost::iostreams;
struct QuoteOutputFilter {
typedef char char_type;
typedef io::output_filter_tag category;
int indent = 0;
template<typename Sink>
bool newLine(Sink& snk)
{
std::string str = "\n" + std::string(indent * 4, ' ');
return io::write(snk, str.c_str(), str.size());
}
template<typename Sink>
bool put(Sink& snk, char c)
{
switch (c)
{
case '<':
io::put(snk, c);
indent += 1;
return newLine(snk);
case ',':
io::put(snk, c);
return newLine(snk);
case '>':
indent -= 1;
newLine(snk);
return io::put(snk, c);
default:
return io::put(snk, c);
}
}
};
int main()
{
io::filtering_ostream out;
out.push(QuoteOutputFilter());
out.push(std::cout);
out << "test0<test1<test2, test3<test4> > >";
}
我想要一些工具,使 std::ostream
(或派生的)在遇到特殊字符(或特殊对象)时自动识别。假设特殊字符是 <
和 >
。在这种情况下,以下输入 test0<test1<test2, test3<test4> > >
应产生以下输出:
test0<
test1<
test2,
test3<
test4
>
>
>
如何实现这一点?
std::ostream
? IOStream 设计相当复杂(而且有点慢),所以我明白您为什么会这样想。 ostream
这个名字听起来是个不错的提示,但实际上作用不大。它通过将 std::ostreambuf
和 operator<<
重载绑定在一起来真正起作用。派生的 ostream
类 提供具体的流缓冲区。
您想要的可能是 streambuf
过滤器。您获取底层的 streambuf,并将其用作输出,但是当您看到 >
boost::iostreams 使这相当容易,您可以定义过滤器,然后将它们与输出流链接在一起,以将输入转换为所需的输出:
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
namespace io = boost::iostreams;
struct QuoteOutputFilter {
typedef char char_type;
typedef io::output_filter_tag category;
int indent = 0;
template<typename Sink>
bool newLine(Sink& snk)
{
std::string str = "\n" + std::string(indent * 4, ' ');
return io::write(snk, str.c_str(), str.size());
}
template<typename Sink>
bool put(Sink& snk, char c)
{
switch (c)
{
case '<':
io::put(snk, c);
indent += 1;
return newLine(snk);
case ',':
io::put(snk, c);
return newLine(snk);
case '>':
indent -= 1;
newLine(snk);
return io::put(snk, c);
default:
return io::put(snk, c);
}
}
};
int main()
{
io::filtering_ostream out;
out.push(QuoteOutputFilter());
out.push(std::cout);
out << "test0<test1<test2, test3<test4> > >";
}