std::regex_token_iterator

来自cppreference.com
< cpp‎ | regex
在标头 <regex> 定义
template<

    class BidirIt,
    class CharT = typename std::iterator_traits<BidirIt>::value_type,
    class Traits = std::regex_traits<CharT>

> class regex_token_iterator
(C++11 起)

std::regex_token_iterator 是访问底层字符序列内每个正则表达式匹配的单独子匹配的只读老式向前迭代器 (LegacyForwardIterator) 。它也可以用于访问没有匹配到给定的正则表达式的序列部分(例如作为记号化器)。

构造时,它构造一个 std::regex_iterator,而在每次自增时,它越过请求的来自当前匹配结果的子匹配,并在自增离开上个子匹配时自增底层的 std::regex_iterator

默认构造的 std::regex_token_iterator 是序列尾迭代器。在抵达最后匹配的最后子匹配自增合法的 std::regex_token_iterator 时,它变得等于序列尾迭代器。进一步解引用或自增它会引发未定义行为。

在恰好变成序列尾迭代器前,如果请求的子匹配下标列表中出现了 -1(非匹配片段),那么 std::regex_token_iterator 可成为后缀迭代器。解引用这种迭代器会返回对应最后匹配和序列结尾之间的字符序列的 match_results。

std::regex_token_iterator 的典型实现保有底层的 std::regex_iterator、请求的子匹配下标的容器(例如 std::vector<int>)、等于子匹配下标的内部计数器、指向当前匹配的当前子匹配的指向 std::sub_match 指针和含有最近非匹配字符序列的 std::match_results 对象(用于记号化器模式)。

类型要求

-
BidirIt 必须符合老式双向迭代器 (LegacyBidirectionalIterator) 的要求。

特化

定义对常用字符序列类型的数个特化:

在标头 <regex> 定义
类型 定义
std::cregex_token_iterator std::regex_token_iterator<const char*>
std::wcregex_token_iterator std::regex_token_iterator<const wchar_t*>
std::sregex_token_iterator std::regex_token_iterator<std::string::const_iterator>
std::wsregex_token_iterator std::regex_token_iterator<std::wstring::const_iterator>

成员类型

成员类型 定义
value_type std::sub_match<BidirIt>
difference_type std::ptrdiff_t
pointer const value_type*
reference const value_type&
iterator_category std::forward_iterator_tag
iterator_concept (C++20) std::input_iterator_tag
regex_type std::basic_regex<CharT, Traits>

成员函数

构造新的 regex_token_iterator
(公开成员函数)
(析构函数)
(隐式声明)
析构 regex_token_iterator ,包含缓存值
(公开成员函数)
赋值内容
(公开成员函数)
(C++20 中移除)
比较两个 regex_token_iterator
(公开成员函数)
访问当前子匹配
(公开成员函数)
推进迭代器到下一个子匹配
(公开成员函数)

注解

程序员负责确保传递给迭代器构造函数的 std::basic_regex 对象活得久于迭代器。因为迭代器存储 std::regex_iterator,它存储指向 regex 的指针,所以在销毁 regex 后自增迭代器会导致未定义行为。

示例

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <regex>
 
int main()
{
    // 记号化(不匹配片段)
    // 注意仅匹配二次 regex :在获得第三值时迭代器是后缀迭代器。
    const std::string text = "Quick brown fox.";
    const std::regex ws_re("\\s+"); // 空白符
    std::copy(std::sregex_token_iterator(text.begin(), text.end(), ws_re, -1),
              std::sregex_token_iterator(),
              std::ostream_iterator<std::string>(std::cout, "\n"));
 
    std::cout << '\n';
 
    // 迭代首个子匹配
    const std::string html = R"(<p><a href="http://google.com">google</a> )"
                             R"(< a HREF ="http://cppreference.com">cppreference</a>\n</p>)
    const std::regex url_re("<\\s*A\\s+[^>]*href\\s*=\\s*\"([^\"]*)\"", std::regex::icase);
    std::copy(std::sregex_token_iterator(html.begin(), html.end(), url_re, 1),
              std::sregex_token_iterator(),
              std::ostream_iterator<std::string>(std::cout, "\n"));
}

输出:

Quick
brown
fox.
 
http://google.com
http://cppreference.com

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
LWG 3698
(P2770R0)
C++20 regex_token_iterator 是贮藏迭代器,但它是 forward_iterator 使之为 input_iterator[1]
  1. 解决方案没有修改 iterator_category,因为把它改成 std::input_iterator_tag 会影响到很多现有代码。