我希望能够解决这样的问题:Getting std :: ifstream to handle LF, CR, and CRLF?其中istream
需要由复杂的分隔符进行标记化;这样,istream
标记的唯一方法是:
istream
个字符中阅读正则表达式非常擅长使用复杂分隔符标记字符串:
string foo{ "A\nB\rC\n\r" };
vector<string> bar;
// This puts {"A", "B", "C"} into bar
transform(sregex_iterator(foo.cbegin(), foo.cend(), regex("(.*)(?:\n\r?|\r)")), sregex_iterator(), back_inserter(bar), [](const smatch& i){ return i[1].str(); });
但是我无法在regex_iterator
上使用istream
:(我的解决方案是淹没istream
,然后在regex_iterator
上运行它,但是啜食步骤似乎是多余的。
在某处有istream_iterator
和regex_iterator
的邪恶组合,或者如果我想要它,我必须自己写吗?
答案 0 :(得分:2)
这个问题是关于代码外观的:
regex
一次只能处理1个字符,所以这个问题要求使用库一次解析istream
1个字符,而不是在内部读取和解析{ {1}}一次1个字符istream
1个字符仍会将该一个字符复制到临时变量(缓冲区),因此该代码试图避免在内部缓冲所有代码,具体取决于库而不是抽象 C ++ 11&#39; istream
使用的ECMA-262不支持预见或后视:https://stackoverflow.com/a/14539500/2642059这意味着regex
只能匹配使用regex
,但显然那些在C ++ 11中实现的不会。
input_iterator_tag
支持boost::regex_iterator
标记(not available in C++11 regex
flags。)boost::match_partial
允许用户啜饮部分该文件并运行boost::match_partial
,由于输入结束不匹配,regex
将&#34;握住它的手指&#34;在正则表达式中的那个位置并等待更多的添加到缓冲区。您可以在此处查看示例:http://www.boost.org/doc/libs/1_55_0/libs/regex/doc/html/boost_regex/partial_matches.html在一般情况下,如regex
,这可以节省缓冲区大小。
"A\nB\rC\n\r"
有4个缺点:
boost::match_partial
这样可以保存用户没有大小,并且他必须啜饮整个"ABC\n"
istream
总是导致膨胀回过头来回答这个问题:标准库boost
无法在regex_iterator
上运行,需要整个input_iterator_tag
。 istream
允许用户可能比整个boost::regex_iterator
更少。因为这是关于代码外观的问题,并且因为istream
的最坏情况需要整个文件的淤塞,所以这不是一个很好的答案。
为了获得最佳代码外观,整个文件以及运行标准boost::regex_iterator
是最好的选择。
答案 1 :(得分:1)
我想不是。 istream_iterator
具有input_iterator_tag
标记,而regex_iterator
期望使用双向迭代器(bidirectional_iterator_tag
)进行初始化。
如果您的分隔符正则表达式足够复杂以避免自己阅读流,那么最好的方法就是确实淹没istream
。