c++ - 如何使用指针调整字符串拆分算法,使其改用迭代器?

标签 c++

下面的代码来自对 this question on string splitting 的回答.它使用指针,对该答案的评论表明它可以适用于 std::string。如何使用 std::string 的特性来实现相同的算法,例如使用迭代器?

#include <vector>
#include <string>
using namespace std;

vector<string> split(const char *str, char c = ',')
{
    vector<string> result;

    do
    {
        const char *begin = str;

        while(*str != c && *str)
          str++;

        result.push_back(string(begin, str));
    } while (0 != *str++);

    return result;
}

好吧,我显然用字符串替换了 char,但后来我注意到他使用了指向字符开头的指针。字符串甚至可能吗?循环终止标准如何变化?进行此更改时还有什么我需要担心的吗?

最佳答案

您可以使用 iterators而不是指针。迭代器提供了一种遍历容器的方法,通常可以将其视为类似于指针。

在这种情况下,您可以使用begin()成员函数(如果不需要修改元素,则可以使用cbegin()) >std::string 对象获取引用第一个字符的迭代器,end()(或cend())成员函数获取一个“最后一个”的迭代器。

对于内循环,你的终止条件是一样的;当您点击要拆分字符串的分隔符时,您想停止。对于外部循环,您可以将迭代器与您已经从 end() 成员函数中获得的结束迭代器进行比较,而不是将字符值与 '\0' 进行比较.算法的其余部分非常相似;迭代器在取消引用和递增方面像指针一样工作:

std::vector<std::string> split(const std::string& str, const char delim = ',') {
    std::vector<std::string> result;

    auto end = str.cend();
    auto iter = str.cbegin();

    while (iter != end) {
        auto begin = iter;

        while (iter != end && *iter != delim) ++iter;

        result.push_back(std::string(begin, iter));
        if (iter != end) ++iter; // See note (**) below.
    }

    return result;
}

请注意内部循环条件中的细微差别:它现在测试我们是否在尝试解除引用之前到达结尾。这是因为我们不能取消引用指向容器末尾的迭代器,所以我们必须在尝试取消引用之前检查这一点。原始算法假定空字符结束字符串,因此我们可以取消引用指向该位置的指针。

(**)iter已经是end时,iter++ != end的有效性正在讨论中在 Are end+1 iterators for std::string allowed? 我已将此 if 语句添加到原始算法中,以在 iter 到达内部循环中的 end 时中断循环。这避免了向已经是 end 迭代器的迭代器添加 1,并避免了潜在的问题。

关于c++ - 如何使用指针调整字符串拆分算法,使其改用迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33629158/

相关文章:

c++ - 递归模板调用中无法调用模板化函数重载

c++ - 获取模块大小

c++ - 是否可以在全局函数中访问类成员?

C++ 映射数组键自动增加

c++ - 在 C++ 代码中无休止地做 while 循环?

c++ - Xcode将简单的C++ 20代码段标记为错误,但使用最新的LLVM 10.0.0 Clang编译器正确编译

c++ - 使用 libcurl 上传文件

c++ - 重命名变量类型

c++ - 将 IO 寄存器作为模板参数传递

c++ - GCC 中的模板看不到在它之后声明的函数,而是在实例化之前