2010-01-18 4 views
10

entfernen Ich bin neu in C++. Ich würde gerne wissen, wie erfahrene Programmierer das machen.Wie alle geraden ganzen Zahlen aus Satz <int> in C++

was ich habe:

set<int> s; 
s.insert(1); 
s.insert(2); 
s.insert(3); 
s.insert(4); 
s.insert(5); 

for(set<int>::iterator itr = s.begin(); itr != s.end(); ++itr){ 
if (!(*itr % 2)) 
    s.erase(itr); 
} 

und natürlich funktioniert es nicht. weil itr nach dem Löschen inkrementiert wird. bedeutet es, dass Itr immer dann auf den Anfang des Sets zeigen muss, nachdem ich das Element aus dem Set gelöscht habe?

Antwort

16
for(set<int>::iterator itr = s.begin(); itr != s.end();){ 
    if (!(*itr % 2)) 
     s.erase(itr++); 

    else ++itr; 
} 

wirksam STL von Scott Myers

+0

Sie haben eine zusätzliche Klammer im Code. – qba

+0

Warum ist itr ++ in der Löschfunktion erlaubt, aber nicht außerhalb? – Quincy

+5

'itr ++' ist draußen erlaubt, aber '++ es' ist im Allgemeinen vorzuziehen, wenn der Wert unbenutzt ist, aus Gründen, die zu mühsam sind, jedes Mal, wenn jemand es macht ;-) In diesem Fall könnte es besser sein ignorieren Sie die übliche gute Praxis und schreiben Sie 'itr ++', nur weil der Code etwas glatter liest, wenn es in beiden Fällen gleich ist. –

11

Das Löschen eines Elements aus std :: set macht nur Iteratoren ungültig, die auf dieses Element zeigen.

Holen Sie einen Iterator zum nächsten Element, bevor Sie das Zielelement löschen.

8

Sie müssen nicht zum Anfang zurückkehren. set::erase entkräftet nur Iteratoren, die auf das Element beziehen wird gelöscht, so brauchen Sie nur den Iterator und Schritt kopieren vor dem Löschen:

for(set<int>::iterator itr = s.begin(); itr != s.end();) 
{ 
    set<int>::iterator here = itr++; 
    if (!(*here % 2)) 
     s.erase(here); 
} 
+0

OK, gebe ich auf. Was ist der Fehler? –

+1

Ich habe mich geirrt, ich dachte du hast das erste Element ausgelassen. Ich nehme meinen Kommentar zurück und lehne ab. –

-1

Der beste Weg, zu verwenden ist und die Kombination von remove_if löschen

s.erase(remove_if(s.begin(), s.end(), evenOddFunctor), s.end()) 

Dies wird hilfreich sein http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove

wirksame STL von Scott Meyers Siehe auch

Edit: Obwohl meine Lösung falsch ist, ich es nicht bin zu löschen. Es könnte ein gutes Lernen für jemanden wie mich sein, der nicht über veränderbare/unveränderliche Iteratoren denkt

+6

'remove_if' erfordert, dass' operator * 'einen nichtkonstanten Wert zurückgibt. std :: set erzwingt, dass es immer geordnet ist; die Rückgabe eines nichtkonstanten L-Wertes aus 'std :: set :: operator *' würde diese Garantie brechen. Daher akzeptiert 'std :: remove_if()' nicht 'std :: set :: iterator's – MSalters

+0

Danke ich weiß nicht, dass –

+5

Das war wirklich hilfreich. Ich habe versucht, dies mit remove_if zu tun und das sagte mir, was das Problem war. Vielen Dank. –