2012-09-12 26 views
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在列表()函數的元素。但我得到一個錯誤,說 「調試斷言失敗!......表達式:列表迭代器不可遞增」 但我們可以遞增迭代器的權利?

+0

刪除後刪除? –

+0

_你在哪裏得到「斷言」?使用調試器來找到它。如果你想知道它發生的時間,請逐行通過代碼。 –

+0

爲什麼將L.erase返回值分配給i2? – Bikush

回答

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的所有元素的一般情況!

+0

擦除/刪除更加地道,但在這種情況下,謂詞需要一些狀態 - 與普通循環相比,它很快就會變得很難看(更多代碼)。 –

+0

@FrerichRaabe真實,謝謝,我添加了一個相應的提示;但這就是爲什麼我在一開始就給出了循環形式的原因;) – codeling

+0

'remove_if'在這裏不會很可靠。沒有承諾它會在整個範圍內按順序應用謂詞,因此要記住索引是奇數還是偶數是不可能的,或者至少不能移植。 –

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); 
} 
1

添加到什麼wOOte說,你可能想使用一個反向迭代來解決這個問題。

+0

+1 - 沒有用std :: list試過,但這通常是我在其他語言中使用動態列表容器類型所做的。 –

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

所以你刪除的第一個元素,跳過第二個,刪除第三個,依此類推。