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() 関数を使用して要素を消去しようとしています。しかし、「Debug assertion failed! ......Expression:list iterator not incrementable」というエラーが表示されますが、イテレータを正しくインクリメントできますか?

4

4 に答える 4

1

技術的にはこの場合ではありません。

Erase()を使用すると、ポイントされたノードが削除されるため、実際には、使用していたイテレータが無効になります。したがって、インクリメントすると、未定義の動作になります。

削除したい位置へのイテレータだけで2番目のリストを作成するのが最善かもしれません。それらを循環して、後でeraseを呼び出すことができます。2番目のリストからイテレータを消去することはないので、機能します。

このようなもの:

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あなたの場合、状態情報(インデックスが奇数か偶数かの情報)が必要になるため、不可能ではないにしても、使用するのは困難です。したがって、上記のループ構造を使用することをお勧めします。特定の述語が true を返すすべての要素を削除する一般的なケースの remove_if に注意してください。

于 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;
    }
}

したがって、最初の要素を削除し、2 番目の要素をスキップし、3 番目の要素を削除する、というようにします。

于 2012-09-12T13:08:00.513 に答える