在 istream 上使用regex_iterator
Using a regex_iterator on an istream
我希望能够解决这样的问题: 获取 std :: ifstream 来处理 LF、CR 和 CRLF? 其中istream
需要由复杂的分隔符标记; 这样标记istream
的唯一方法是:
- 一次
istream
一个字符地阅读它 - 收集字符
- 命中分隔符时,将集合作为标记返回
正则表达式非常擅长使用复杂的分隔符标记字符串:
string foo{ "AnBrCnr" };
vector<string> bar;
// This puts {"A", "B", "C"} into bar
transform(sregex_iterator(foo.cbegin(), foo.cend(), regex("(.*)(?:nr?|r)")), sregex_iterator(), back_inserter(bar), [](const smatch& i){ return i[1].str(); });
但我不能在istream
:(上使用regex_iterator
我的解决方案是啜饮istream
,然后在上面运行regex_iterator
,但啜饮步骤似乎是多余的。
是否有istream_iterator
和regex_iterator
的邪恶组合,或者如果我想要它,我必须自己写吗?
这个问题是关于代码外观的:
- 由于我们知道
regex
一次可以工作 1 个字符,因此这个问题要求使用库一次解析 1 个字符istream
,而不是在内部一次读取和解析 1 个字符istream
- 由于一次解析 1 个字符
istream
仍将该字符复制到临时变量(缓冲区),因此此代码试图避免在内部缓冲所有代码,而是依赖于库来抽象
C++11 的regex
使用 ECMA-262,它不支持向前看或向后看: https://stackoverflow.com/a/14539500/2642059 这意味着regex
可以仅使用input_iterator_tag
进行匹配,但显然在 C++11 中实现的那些不能。
另一方面,boost::regex_iterator
确实支持boost::match_partial
标志(在 C++11regex
标志中不可用)。boost::match_partial
允许用户啜饮文件的一部分并在其上运行regex
,在由于输入结束而导致不匹配时,regex
将在正则表达式中的该位置"握住手指"并等待更多添加到缓冲区中。您可以在此处看到一个示例:http://www.boost.org/doc/libs/1_55_0/libs/regex/doc/html/boost_regex/partial_matches.html 在一般情况下,如"AnBrCnr"
,这可以节省缓冲区大小。
boost::match_partial
有 4 个缺点:
- 在最坏的情况下,就像
"ABCn"
这样,这不会为用户节省任何尺寸,他必须啜饮整个istream
- 如果程序员可以猜出缓冲区大小太大,即它包含分隔符和大量缓冲区大小,则减少缓冲区大小的好处就会被浪费掉。
- 每当选择的缓冲区大小太小时,与整个文件的啜饮相比,都需要额外的计算,因此此方法在分隔符密集字符串中表现出色
- 包含
boost
总是会导致膨胀
回过头来回答这个问题:一个标准的库regex_iterator
不能在input_iterator_tag
上运行,需要整个istream
。boost::regex_iterator
允许用户可能比整个istream
咕噜咕噜。因为这是一个关于代码外观的问题,而且因为boost::regex_iterator
最坏的情况无论如何都需要整个文件,所以它不是这个问题的一个好答案。
为了获得最佳代码外观,最好选择对整个文件进行扫描并对其运行标准regex_iterator
。
我认为不是。istream_iterator
具有input_iterator_tag
标记,而regex_iterator
期望使用双向迭代器 (bidirectional_iterator_tag
) 进行初始化。
如果您的分隔符正则表达式足够复杂,可以避免自己读取流,那么最好的方法是确实啜istream
- 此模式的C++RegEx
- 在调试模式下引发C++ "deque iterator not dereferencable"异常
- std::iterator::reference 必须是引用吗?
- C++ std::regex 使用前瞻失败
- std::regex:匹配由数字和空格组成的字符串,并提取数字.如何?
- 为什么unordered_set<string::iterator>不起作用?
- 造成致命错误:boost/fusion/iterator/equal_to.hpp 没有这样的文件或目录
- Visual accept std::string from std::byte iterator
- 使用 boost::regex 从目录中获取带有一些正则表达式的文件名称时出现意外输出
- 你能防止 std::regex 在无效表达式上抛出异常吗?
- 使用Regex解析cpp中的字符串并创建映射
- C++:如何用split查找单词?Regex
- 在VC2015U3上,std::regex比boost::regex慢得多
- 是否有更有效的方法来生成日期的REGEX字符串
- 在C++中使用带有regex的捕获组
- 将std::regex设置为静态的好主意吗
- 为什么Regex(c++)需要指数时间
- std::regex and dual ABI
- C++11 std::regex后备选项
- 什么是"std::set<int,int>::iterator"?