Iterator einer Multimap lässt sich nicht inkrementieren
-
Hallo alle zusammen

Ich lerne gerade mit Hilfe des Buches C++ - Primer das Programmieren. In diesem Buch befinden sich viele Übungsaufgaben, die ich allesamt immer versuche so gut es geht zu lösen. Momentan versuche ich mich an folgender Aufgabe:
Schreiben Sie ein Programm, das eine Multimap mit Autoren und ihren Werken füllt. Benutzen Sie find, um ein Element zu finden, und löschen Sie es. Vergewissern Sie sich, dass das Programm korrekt arbeitet, wenn sich das Element, nachdem Sie suchen, nicht in der Map befindet.
Ich habe das Programm auch schon fertig geschrieben:
//main.cpp #include <iostream> #include <string> #include <map> using std::cout; using std::endl; using std::cin; using std::string; using std::multimap; using std::make_pair; int main() { multimap<string, string> autoren; string suchbegriff; // Die multimap mit ein paar Werten füllen autoren.insert(make_pair("Oliver", "Fairwater")); autoren.insert(make_pair("Oliver", "Test")); autoren.insert(make_pair("Gott", "Die Bibel")); autoren.insert(make_pair("Oliver", "Show")); cout << "Inhalt der multimap:" << endl; // typedef um die lange Iterator- und Size_Type-Initialisierung zu verkürzen typedef multimap<string, string>::iterator aut_it; typedef multimap<string, string>::size_type sz_type; // Ausgabe aller Elemente der multimap for (aut_it iter = autoren.begin(); iter != autoren.end(); ++iter) cout << "Autor: " << iter->first << " / Titel: " << iter->second << endl; cout << "\nWelches Element soll geloescht werden?" << endl; getline(cin, suchbegriff); // Durchsucht multimap nach einem Schlüssel der mit der Eingabe übereinstimmt // Gibt Anzahl der Elemente mit diesem Schlüssel zurück sz_type anzahl = autoren.count(suchbegriff); // Gibt Iterator zurück der auf das erste Element mit diesem Schlüssel zeigt aut_it mm_iter = autoren.find(suchbegriff); // Löscht alle Elemente mit dem angegebenen Schlüssel for (sz_type i = 0; i != anzahl; ++i, ++mm_iter) autoren.erase(mm_iter); // Ausgabe der noch übrigen Elemente der multimap if (autoren.size() != 0) { cout << "\nAusgabe der noch uebrigen Elemente:" << endl; for (aut_it iter = autoren.begin(); iter != autoren.end(); ++iter) cout << "Autor: " << iter->first << " / Titel: " << iter->second << endl; } else cout << "\nIn der multimap befinden sich keine Elemente mehr." << endl; return 0; }Und es lässt sich auch problemlos kompilieren. Wenn ich allerdings den Namen eines Autors, dessen Elemente in der Multimap gelöscht werden sollen, eingebe, erhalte ich eine Fehlermeldung: "Expression: map/set iterator not incrementable"
Hier mal ein Bild eines Testlaufs des Programms:
http://img293.imageshack.us/my.php?image=mmapiterinkrementierfehbs6.jpgSoweit wie ich den Fehler verstanden habe, lässt sich der Multimap-Iterator der folgenden for-Schleife nicht inkrementieren:
// Löscht alle Elemente mit dem angegebenen Schlüssel for (sz_type i = 0; i != anzahl; ++i, ++mm_iter) autoren.erase(mm_iter);Was ich aber überhaupt nicht verstehe, da ich in einer vorherigen for-Schleife auch einen Multimap-Iterator inkrementiere und dort das ganze problemlos funktioniert:
// Ausgabe aller Elemente der multimap for (aut_it iter = autoren.begin(); iter != autoren.end(); ++iter) cout << "Autor: " << iter->first << " / Titel: " << iter->second << endl;Meine Frage ist jetzt, ob mir jemand erklären kann, wieso ich in der einen for-Schleife einen Multimap-Iterator problemlos inkrementieren kann, in einer anderen for-Schleife jedoch nicht. Vielleicht habe ich aber auch die Fehlermeldung falsch verstanden... Ich bin also momentan total ratlos

-
Ich bin mir jetzt nicht sicher, aber es könnte sein, dass der Iterator ungültig wird, wenn du das Element rauslöschst. Dadurch ist er nicht mehr inkrementierbar.
Am besten ersetzt du deinen Code:// Gibt Iterator zurück der auf das erste Element mit diesem Schlüssel zeigt aut_it mm_iter = autoren.find(suchbegriff); // Löscht alle Elemente mit dem angegebenen Schlüssel for (sz_type i = 0; i != anzahl; ++i, ++mm_iter) autoren.erase(mm_iter);Durch:
autoren.erase(suchbegriff);Kannst du auch hier nachschauen:
http://www.cplusplus.com/reference/stl/multimap/erase.htmlGrüssli
-
Erstmal vielen Dank für deine Antwort :). Ich habe auch gleich mal, dank deines Tipps, die entsprechende for-Schleife folgendermaßen umgeschrieben:
for (sz_type i = 0; i != anzahl; ++i) { // Gibt Iterator zurück der auf das erste Element mit diesem Schlüssel zeigt aut_it mm_iter = autoren.find(suchbegriff); autoren.erase(mm_iter); }Und siehe da, jetzt funktioniert das Programm einwandfrei. Du hattest also völlig recht. Der Iterator wird durch das Löschen eines Elementes in der Multimap ungültig. Danke nochmal

-
Aber dein Code ist immer noch unnötig aufwendig. Du kannst auf die for-Schleife ganz verzichten. Übergib der
eraseFunktion einfach den Suchbegriff und es werden automatisch alle Einträge mit dem Suchbegriff gelöscht.Grüssli
-
Ja, da hast du auch völlig recht und genau so wie du es sagst steht es auch in dem Buch C++ - Primer. Allerdings ging es in der Übungsaufgabe des Buches darum, der erase-Operation nicht direkt einen Schlüssel zu übergeben, sondern die Elemente der Multimap mit der find-Operation und einem Iterator zu löschen. Darum der ganze Aufwand

-
Oh, sorry, ich vergass die Aufgabenstellung. Allerdings finde ich das eine seltsame Aufgabe, dass ist doch extrem bescheuert, so wird man die Elemente sicher nie rauslöschen. Oder womöglich ging es genau darum, dass man erkennt, das ein Iterator ungültig wird. Naja ka ..
Grüssli