2
#include<iostream>
#include<list>
using namespace std;

void compute(int num)
{
list<int> L;
list<int>::iterator i;
list<int>::iterator i2;
int p;
cout<<"Enter the number of numbers\n";
cin>>p;
int a;
for(int k=1;k<=p;k++)
{
    cin>>a;
    L.push_back(k);
}
cout<<endl;
for(i=L.begin() ; i!=L.end() ; ++i)
{
    cout<<*i<<endl;
}

long int k=1;

for(i=L.begin() ; i!=L.end() ; ++i )
{
    if(k%2!=0) //This is where I try and delete values in odd positions
    {
        i2=L.erase(i);
    }
    k++;
}

for(i=L.begin() ; i!=L.end() ; ++i )
{
    cout<<*i<<endl;
}

}

int main()
{
//  int testcases, sailors;
//cin>>testcases;

//for(int i=1 ; i<=testcases ; i++)
{
//  cin>>sailors;
}
//for(int i=1;i<=testcases;i++)
{
//  int num;
    //cin>>num;
    //compute(num);
}
compute(0);
return 0;

}

我正在尝试使用列表中的 L.erase() 函数擦除元素。但是我收到一条错误消息,说“调试断言失败!......表达式:列表迭代器不可增加”但我们可以增加迭代器,对吗?

4

4 回答 4

1

从技术上讲,在这种情况下不是。

当您使用 erase() 时,您删除了指向的节点,因此您实际上使您所在的迭代器无效。因此,当您增加它时,它是未定义的行为。

最好创建第二个列表,其中仅包含您要删除的位置的迭代器,然后您可以循环遍历这些列表并在之后调用擦除。您不会从第二个列表中删除迭代器,所以它会起作用。

像这样的东西:

List<IteratorType> deleteList;

//Populate deleteList with every other element from original list.

for (List<IteratorType>::iterator iter = deleteList.begin();
         iter !=deleteList.end; ++iter)
{
    originalList.erase(*iter);
}
于 2012-09-12T13:04:39.237 回答
1

除了 wOOte 所说的,您可能希望使用反向迭代器来解决这个问题。

于 2012-09-12T13:07:25.670 回答
1

erase使作为参数传入的迭代器无效 - 因为迭代器指向的位置的元素刚刚被擦除!在同一个迭代器上,在代码的下一个 for 循环中尝试递增!这就是它失败的原因。

但是,擦除它会返回一个指向新位置的迭代器,我们可以使用它;因此,您从 STL 容器中删除某些内容的循环应如下所示;我用你使用的类型来展示它,列表,但你也可以使用例如向量:

list<int> L;
// ...
list<int>::iterator it=L.begin();
while (it!=L.end())
{
    if(eraseCondition)
    {
        it=L.erase(it);
    }
    else
    {
        ++it;
    }
}

或者,如果可能,最好使用std::remove_if

container.erase(std::remove_if(L.begin(), L.end(), predicate), L.end());

在您的情况下,这将很难(如果不是不可能的话)使用,因为它predicate需要状态信息(索引是奇数还是偶数的信息)。所以我建议使用上面提到的循环结构;请记住 remove_if 对于删除某个谓词返回 true 的所有元素的一般情况!

于 2012-09-12T13:07:41.083 回答
0

迭代器i因调用而失效erase;但是,在for循环的下一次迭代中,您尝试增加它 - 这是无效的。

尝试

for(i=L.begin() ; i!=L.end() ; )
{
    if(k%2!=0) //This is where I try and delete values in odd positions
    {
        i=L.erase(i);
    } else {
        ++i;
    }
    k++;
}

相反 - 如果您不擦除,则仅增加迭代器(擦除基本上“推进”迭代器,因为它会产生一个迭代器到您擦除的元素之后的元素)。

您实际上可以利用这种行为erase来编写您的函数,而无需k

i = L.begin();
while ( i != L.end() ) {
    i = L.erase( i );      // Delete one
    if ( i != L.end() ) {  // Skip next, if there's an element
      ++i;
    }
}

所以你删除第一个元素,跳过第二个,删除第三个,依此类推。

于 2012-09-12T13:08:00.513 回答