关于c ++:如何使用指针调整字符串拆分算法,以便使用迭代器?


How to adapt a string splitting algorithm using pointers so it uses iterators instead?

下面的代码来自这个关于字符串拆分的问题的答案。它使用指针,对这个答案的评论表明它可以适用于std::string。如何使用std::string的特性来实现相同的算法,例如使用迭代器?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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,但后来我注意到他使用的是指向字符开头的指针。这对弦来说是可能的吗?循环终止条件如何更改?做这个改变时还有什么需要担心的吗?


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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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();

    do {
        auto begin = iter;

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

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

    return result;
}

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

(**)当EDCOX1〔8〕已为end时,EDCOX1〔7〕的有效性在STE::String允许的结尾+ 1迭代器中讨论吗?我在原始算法中添加了这个if语句,以便在iter在内部循环中到达end时中断循环。这避免了向已经是end迭代器的迭代器添加一个迭代器,并避免了潜在的问题。