C++如何实现返回迭代器供调用方构造任意STL容器的字符串分词函数
C++ 分词迭代器实现方案
你需要的是符合STL迭代器规范的惰性分词迭代器,不需要提前把所有分词结果存入中间容器,直接返回迭代器对即可让调用方初始化任意STL容器。
核心实现要点
- 迭代器必须符合C++标准的输入迭代器类别,这是STL容器构造要求的最低迭代器类别
- 推荐用
string_view存储分词结果,避免不必要的字符串拷贝,大幅提升性能 - end迭代器用空哨兵实现,不需要提前遍历整个字符串计算总分词数
最简实现示例
以下示例以空格为默认分隔符,你可以自行替换分隔符匹配逻辑:
#include <iterator> #include <string_view> #include <cctype> class SplitIterator { public: // 迭代器特性定义,必须声明才能兼容STL算法和容器 using iterator_category = std::input_iterator_tag; using value_type = std::string_view; using difference_type = std::ptrdiff_t; using pointer = const value_type*; using reference = const value_type&; // 构造end哨兵的默认构造函数 SplitIterator() = default; // 构造begin迭代器的构造函数 explicit SplitIterator(std::string_view input) : input_(input) { next(); // 初始化时直接定位第一个分词 } // 解引用运算符重载 reference operator*() const { return current_; } pointer operator->() const { return ¤t_; } // 自增运算符重载 SplitIterator& operator++() { next(); return *this; } SplitIterator operator++(int) { auto temp = *this; next(); return temp; } // 迭代器比较逻辑,和哨兵比较时判断是否遍历结束 bool operator==(const SplitIterator& other) const { return input_.empty() && other.input_.empty(); } bool operator!=(const SplitIterator& other) const { return !(*this == other); } private: std::string_view input_; std::string_view current_; void next() { // 跳过开头的空格分隔符,可自行替换为自定义分隔符逻辑 while (!input_.empty() && std::isspace(static_cast<unsigned char>(input_.front()))) { input_.remove_prefix(1); } if (input_.empty()) { current_ = {}; return; } // 查找当前分词的结束位置 size_t end_pos = 0; while (end_pos < input_.size() && !std::isspace(static_cast<unsigned char>(input_[end_pos]))) { end_pos++; } current_ = input_.substr(0, end_pos); input_.remove_prefix(end_pos); } }; // 封装成分割函数,返回可直接遍历的范围对象 auto split(std::string_view input) { struct Range { SplitIterator begin_; SplitIterator end_; SplitIterator begin() const { return begin_; } SplitIterator end() const { return end_; } }; return Range{SplitIterator(input), SplitIterator{}}; }
调用示例
返回的迭代器范围可以直接用来构造任意STL容器,也支持范围for遍历:
#include <vector> #include <list> #include <set> #include <iostream> int main() { std::string test_str = "hello world test split iterator"; // 构造vector std::vector<std::string_view> vec(split(test_str).begin(), split(test_str).end()); // 构造list std::list<std::string> lst(split(test_str).begin(), split(test_str).end()); // 构造set std::set<std::string> str_set(split(test_str).begin(), split(test_str).end()); // 直接范围for遍历 for (auto word : split(test_str)) { std::cout << word << '\n'; } return 0; }
扩展优化思路
- 如果需要自定义分隔符,可以给
SplitIterator添加模板参数或者构造函数参数,传入自定义的分隔符判断可调用对象 - 使用C++20及以上版本的场景下,可以直接调用标准库的
std::ranges::split_view,不需要自行实现迭代器,原生支持用范围构造STL容器 - 如果需要适配宽字符或者其他字符类型,可以将迭代器改造为模板类,适配
wstring_view等不同字符类型的视图
内容的提问来源于stack exchange,提问作者user1408865
相关产品推荐
相关产品推荐

