如何将std::string分割为连续非空白字符序列并获取对应迭代器
C++ 分割字符串为非空白字符序列并获取迭代器
这个需求用C++标准库的工具就能轻松搞定,最简洁可靠的方案是借助std::istringstream配合std::istream_iterator,完美适配你提到的所有场景——不管字符串开头有多少空白,序列间空白数量不确定,都能准确分割出连续的非空白字符序列,还能通过迭代器逐个访问。
核心实现代码
下面是完整的示例代码,直接就能用:
#include <iostream> #include <sstream> #include <string> #include <iterator> #include <vector> int main() { std::string test(" 35.3881 12.3637 39.3485"); std::istringstream iss(test); // 初始化迭代器,指向第一个非空白序列 std::istream_iterator<std::string> token_it(iss); // 迭代器末尾标记 std::istream_iterator<std::string> end_it; // 遍历迭代器,逐个访问分割后的序列 for (; token_it != end_it; ++token_it) { std::cout << "当前序列: " << *token_it << std::endl; } // 也可以直接把所有序列存入容器(比如vector) std::vector<std::string> all_tokens(token_it, end_it); for (const auto& token : all_tokens) { std::cout << "容器中的序列: " << token << std::endl; } return 0; }
方案说明
std::istringstream会自动处理所有类型的空白字符(空格、制表符、换行符等),包括开头的任意数量空白,以及序列间的任意数量空白,完全符合你的需求。std::istream_iterator<std::string>的工作逻辑就是每次迭代读取下一个非空白的字符串,初始状态指向第一个有效序列,递增后自动跳到下一个,直到到达字符串末尾(和end_it相等)。- 这个方案不需要自己处理复杂的字符串遍历和边界判断,标准库已经帮你封装好了所有细节,代码简洁且不易出错。
替代方案(手动实现迭代器)
如果出于某些原因不想用流,也可以自定义一个迭代器来实现,但需要自己处理空白跳过和序列提取:
#include <string> #include <iterator> #include <cctype> class TokenIterator : public std::iterator<std::forward_iterator_tag, std::string> { private: const std::string* str_; size_t pos_; void skip_whitespace() { while (pos_ < str_->size() && std::isspace((*str_)[pos_])) { ++pos_; } } public: TokenIterator() : str_(nullptr), pos_(0) {} explicit TokenIterator(const std::string& str) : str_(&str), pos_(0) { skip_whitespace(); } std::string operator*() const { size_t start = pos_; while (pos_ < str_->size() && !std::isspace((*str_)[pos_])) { ++pos_; } return str_->substr(start, pos_ - start); } TokenIterator& operator++() { skip_whitespace(); return *this; } bool operator==(const TokenIterator& other) const { return str_ == other.str_ && pos_ == other.pos_; } bool operator!=(const TokenIterator& other) const { return !(*this == other); } }; // 使用示例 int main() { std::string test(" 35.3881 12.3637 39.3485"); TokenIterator it(test); TokenIterator end; for (; it != end; ++it) { std::cout << *it << std::endl; } return 0; }
不过这种方法需要自己处理很多细节(比如空白判断、边界溢出等),除非有特殊需求,否则更推荐用标准库的流迭代器方案。
内容的提问来源于stack exchange,提问作者0xbadf00d
相关产品推荐
相关产品推荐

