为什么在迭代该向量时会出现分段错误?

发布于 2024-12-07 08:14:44 字数 440 浏览 1 评论 0原文

我需要遍历这个向量并删除重复项。这段代码中的某个地方发生了分段错误。我的猜测是,它与迭代器运行时删除元素有关,但我还没有真正了解这些迭代器的实际工作原理,所以我无法弄清楚。

vector<char *>::iterator iter;
for (iter = v->begin(); iter != v->end()-1; iter++ ){
    char *aString = *iter;
    int n = 1;
    while(iter+n != v->end()){
        int comparison = strcmp(aString, *(iter+n));
        if(comparison == 0){
            v->erase(iter + n);
        }
        n++;
    }
}

I need to go through this vector and delete the duplicates. A segmentation fault is occurring somewhere within this code. My guess is that it has something to do with deleting elements while the iterator is going through, but I don't really have a concrete understanding of how these iterators are actually working yet, so I can't figure it out.

vector<char *>::iterator iter;
for (iter = v->begin(); iter != v->end()-1; iter++ ){
    char *aString = *iter;
    int n = 1;
    while(iter+n != v->end()){
        int comparison = strcmp(aString, *(iter+n));
        if(comparison == 0){
            v->erase(iter + n);
        }
        n++;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼趣 2024-12-14 08:14:44

确实,这里只是遇到了几个一对一的问题。当您删除一个元素时,您与 end() 进行了错误的比较并递增了 n

for (iter = v->begin(); iter != v->end()-1; iter++ ){
                                  ^^^^^^^^

下面

while(iter+n != v->end())
             ^^

将执行您想要的操作(并证明它有效):

int main()
{

    std::vector<const char*> v (4, "this");
    std::vector<const char *>::iterator iter;

    for (iter = v.begin(); iter <  v.end(); iter++ ) {
        std::cout << *iter << " ";
    }
    std::cout << std::endl;

    for (iter = v.begin(); iter <  v.end(); iter++ ){
        const char *aString = *iter;
        int n = 1;
        while(iter+n < v.end()){
            int comparison = strcmp(aString, *(iter+n));
            if(comparison == 0){
                v.erase(iter + n);
            }
            else
                n++;
        }
    }

    for (iter = v.begin(); iter <  v.end(); iter++ ) {
        std::cout << *iter << std::endl;
    }

}

输出是:

这个这个这个这个
这个

Really, you just have a couple off-by-one problems here. You were comparing incorrectly against end() and incrementing n when you erased an element:

for (iter = v->begin(); iter != v->end()-1; iter++ ){
                                  ^^^^^^^^

And

while(iter+n != v->end())
             ^^

The following will do what you want (and demonstrate that it works):

int main()
{

    std::vector<const char*> v (4, "this");
    std::vector<const char *>::iterator iter;

    for (iter = v.begin(); iter <  v.end(); iter++ ) {
        std::cout << *iter << " ";
    }
    std::cout << std::endl;

    for (iter = v.begin(); iter <  v.end(); iter++ ){
        const char *aString = *iter;
        int n = 1;
        while(iter+n < v.end()){
            int comparison = strcmp(aString, *(iter+n));
            if(comparison == 0){
                v.erase(iter + n);
            }
            else
                n++;
        }
    }

    for (iter = v.begin(); iter <  v.end(); iter++ ) {
        std::cout << *iter << std::endl;
    }

}

Output is:

this this this this
this

各自安好 2024-12-14 08:14:44

您没有正确迭代向量的其余部分。 Beta 建议的另一种方法是将擦除删除与remove_if 结合使用。像这样:

bool compare_strings(char * aString,char * bString)
{
    return 0==strcmp(aString,bString);
}

void remove_duplicates(vector<char *> * v)
{
    vector<char *>::iterator iter;
    for (iter = v->begin(); iter != v->end(); iter++ ) {
        v->erase(std::remove_if(iter+1,v->end(),compare_strings),v->end());
    }
}

You are not properly iterating through the remainder of the vector. An alternative to what Beta suggested is to use erase-remove with remove_if. Like this:

bool compare_strings(char * aString,char * bString)
{
    return 0==strcmp(aString,bString);
}

void remove_duplicates(vector<char *> * v)
{
    vector<char *>::iterator iter;
    for (iter = v->begin(); iter != v->end(); iter++ ) {
        v->erase(std::remove_if(iter+1,v->end(),compare_strings),v->end());
    }
}
莫相离 2024-12-14 08:14:44

当您从向量中删除一个元素时,向量会缩短一个元素。试试这个:

if(comparison == 0){
  v->erase(iter + n);
}
else{
  n++;
}

When you erase an element from the vector, the vector gets one element shorter. Try this:

if(comparison == 0){
  v->erase(iter + n);
}
else{
  n++;
}
同展鸳鸯锦 2024-12-14 08:14:44

从向量中擦除会使从擦除开始的所有迭代器无效,因此您可能不应该按照您的方式构建循环,而应该使用如下标准习惯用法:

for (auto it = v.begin(); it != v.end(); ++it)   // no end() - 1 -- may not be legal!
{
  for (auto jt = it; jt != v.end(); )
  {
    if (jt == it) continue;

    if (strcmp(*it, *jt) == 0)
    {
      jt = v.erase(jt);
    }
    else
    {
      ++jt;
    }
  }
}

此代码避免了对空向量的检查,您的代码无法考虑到空向量为了。

Erasing from a vector invalidates all iterators from the erasee onwards, so you should probably not construct your loop the way you do, and rather use a standard idiom like this:

for (auto it = v.begin(); it != v.end(); ++it)   // no end() - 1 -- may not be legal!
{
  for (auto jt = it; jt != v.end(); )
  {
    if (jt == it) continue;

    if (strcmp(*it, *jt) == 0)
    {
      jt = v.erase(jt);
    }
    else
    {
      ++jt;
    }
  }
}

This code avoids the check for an empty vector, which your code fails to account for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文