【问题标题】:Using a regex_iterator on an istream在 istream 上使用 regex_iterator
【发布时间】:2015-07-05 21:25:55
【问题描述】:

我希望能够解决这样的问题:Getting std :: ifstream to handle LF, CR, and CRLF? 其中istream 需要用复杂的分隔符进行标记;这样标记istream 的唯一方法是:

  1. istream 中一次读取一个字符
  2. 收集人物
  3. 当分隔符被击中时,将集合作为标记返回

正则表达式非常擅长用复杂的分隔符标记字符串:

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(); });

但我不能在istream 上使用regex_iterator :( 我的解决方案是先吃istream,然后在上面运行regex_iterator,但吃这一步似乎是多余的。

在某处是否存在 istream_iteratorregex_iterator 的邪恶组合,或者如果我想要它,我必须自己编写吗?

【问题讨论】:

    标签: c++ regex iterator istream istream-iterator


    【解决方案1】:

    我认为不会。 istream_iterator 具有 input_iterator_tag 标签,而 regex_iterator 期望使用双向迭代器 (bidirectional_iterator_tag) 进行初始化。

    如果您的分隔符正则表达式足够复杂而无法自己读取流,那么最好的方法是确实吞下istream

    【讨论】:

      【解决方案2】:

      这个问题是关于代码外观的:

      1. 因为我们知道 regex 一次只能处理 1 个字符,所以这个问题要求使用库一次解析 istream 1 个字符,而不是在内部读取和解析 istream 1 个字符一次
      2. 由于一次解析 istream 1 个字符仍会将该字符复制到临时变量(缓冲区),此代码旨在避免在内部缓冲所有代码,这取决于库而不是抽象它

      C++11 的regexes 使用不支持前瞻或后瞻的 ECMA-262:https://stackoverflow.com/a/14539500/2642059 这意味着 regex 可以仅使用 input_iterator_tag 匹配,但显然那些在 C 中实现++11 不要。

      另一方面,

      boost::regex_iterator 支持boost::match_partial 标志(即not available in C++11 regex flags。)boost::match_partial 允许用户啜饮部分文件并运行regex除此之外,由于输入结束导致不匹配,regex 将在正则表达式中的该位置“握住它的手指”并等待更多内容添加到缓冲区中。您可以在此处查看示例:http://www.boost.org/doc/libs/1_55_0/libs/regex/doc/html/boost_regex/partial_matches.html 在一般情况下,如"A\nB\rC\n\r",这可以节省缓冲区大小。

      boost::match_partial 有 4 个缺点:

      1. 在最坏的情况下,像 "ABC\n" 这样可以节省用户 no 的大小,他必须啜饮整个 istream
      2. 如果程序员可以猜出一个太大的缓冲区大小,即它包含分隔符和更多的内容,那么减少缓冲区大小的好处就被浪费了
      3. 任何时候选择的缓冲区太小,与整个文件的 slurping 相比,都需要额外的计算,因此这种方法在分隔符密集的字符串中表现出色
      4. 包含boost 总是会导致臃肿

      回过头来回答问题:标准库regex_iterator 不能对input_iterator_tag 进行操作,需要对整个istream 进行啜饮。 boost::regex_iterator 允许用户可能啜饮少于整个 istream。因为这是一个关于代码外观的问题,而且因为boost::regex_iterator 的最坏情况需要对整个文件进行 slurping,所以这不是这个问题的好答案。

      为了获得最佳的代码外观,最好在整个文件上运行标准 regex_iterator

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-23
      • 1970-01-01
      • 1970-01-01
      • 2015-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多