Iteratorelement löschen innerhalb der eigenen Iteratorschleife
-
Hallo liebe Problemlöser,
ich habe mir folgendes Problem angelacht:
Mit den Iteratoren iter1 und iter2 wird mit 2 Forschleifen über die pClusterList gegangen. Sozusagen wird jeder Cluster mit jedem verglichen. Es findetn ein continue statt, wenn beide Cluster gleich sind. Das Ziel ist 2 Cluster zu mergen, die kleiner als ein Vorgabewert voneinander entfernt sind. Seltsamerweise hat dieser Code im Studio 2003 funktioniert nur bekomme ich im VS 2008 nun den Fehler, den ich unter dem Code beschreibe.list<CCluster*>::iterator iter2; list<CCluster*>::iterator iter1; for (iter1 = pClusterList->begin(); iter1 != pClusterList->end(); iter1++) { pCi = *iter1; if ((pCi->pointList.size() < 1)) continue; for (iter2 = pClusterList->begin(); iter2 != pClusterList->end(); iter2++) { pCj = *iter2; if ((pCj->pointList.size() < 1) || (pCi == pCj)) continue; // Get closest point pair distance /*...berechne distanz, wenn diese kleiner ist als fMinDist Merge die Beiden Cluster (Punktelisten)...*/ if (fDistance > fMinDist) continue; // Merge clusters for (pointIter1 = pCj->pointList.begin(); pointIter1 != pCj->pointList.end(); pointIter1++){ pMi = (PointToTrack*) *pointIter1; pCi->addPoint(pMi); //hinzufügen des Punktes } // for delete *iter2; pClusterList->erase(iter2++); } // for } // forIn Zeile 17 - 20 findet das eigentlich Mergen statt, danach soll der Cluster, welcher gerade einem anderen hinzugefügt wurde gelöst werden, wie in den Zeilen 21 und 22. Das Problem dabei ist ein wie ihn VS 2008 nennt "Expression: list iterator not incrementable". Soweit so gut, der Fehler liegt also daran, dass ich den iter2 in Zeile 22 erhöhe und er dann nochmals am For-Schleifenstart (zeile
erhöht wird. Bei einer Anzahl von 2 Clustern in der "pClusterList" zeigt iter2 dann irgendwohin nur nicht ans Ende von pClusterList.
Frage: Wie also kann ich den eben hinzugefügten Cluster aus der Liste löschen ohne dabei überläufe zubekommen?
Der Code ist eigentlich recht simpel und leicht verständlich, mir fehlt aber wohl das technische know-how um hier eine Lösung zu finden.Über eure Hilfe wäre ich sehr dankbar.
Grüße
-
Hier liegt der Hase begraben: pClusterList->erase(iter2++);
Armer Hase...Im Grunde läuft es so:
for(iter = v.begin(); iter != v.end(); /* ... */) { // ... if(wegdamit) { iter = v.erase(iter); } else { ++iter; } }Also mit der Rückgabe von erase arbeiten.
-
pClusterList->erase(iter2++);das würde ich so schreiben:
iter2 = ClusterList->erase(iter2);mach es so:
iter2 = pClusterList->erase(iter2); if (iter2 == pClusterList->End()) break;
-
Solange das iter2++ in der Schleife nicht verschwindet, wird er nach jeder Löschung ein Element überspringen, da erase einen Iterator auf das nächste Element zurückgibt.
-
for (iter1 = pClusterList->begin(); iter1 != pClusterList->end(); ++iter1) { pCi = *iter1; if ((pCi->pointList.size() < 1)) continue; for (iter2 = iter1, ++iter2; iter2 != pClusterList->end(); ) { pCj = *iter2; if ((pCj->pointList.size() < 1) || distance(pCi,pCj) > fMinDist ) { ++iter2; continue; } // hier ließe sich auch find_if einsetzen // Merge clusters for (pointIter1 = pCj->pointList.begin(); pointIter1 != pCj->pointList.end(); pointIter1++){ pMi = (PointToTrack*) *pointIter1; pCi->addPoint(pMi); //hinzufügen des Punktes } // for pClusterList->erase(iter2++); delete pCj; } // for }Baue kleinere Funktionen, und solche Dinge werden einfach.
-
Ok ich werd die guten Tipps gleich umsetzen, melde mich mit Ergebnissen ...
-
Also ich wollte es ja nicht so recht glauben, aber mein Kollege meinte das wäre das beste Forum überhaupt.
Aussage Bestätigt!!Solved: Mit dem Vorschlag von helferlein
iter2 = pClusterList->erase(iter2); if (iter2 == pClusterList->End()) break;@camper, deine Version werde ich auch noch ausprobieren, da ich aber unter Zeitdruck stehe muss es jetzt erstmal so tun.
Thx leutz!
...Ne doch keine Lösung siehe weiter unten
-
bananaslip schrieb:
iter2 = pClusterList->erase(iter2); if (iter2 == pClusterList->End()) break;Wenn dich so etwas nicht erschaudern lässt, weise ich einfach mal darauf hin, dass du so das Element nach einem gelöschten Element überspringst. Zwar ist deine innere Schleife ohnehin ineffizient, da so jede Paarung doppelt geprüft wird, und somit eine Chance besteht, dass das übersprungene Element doch noch einmal behandelt wird, gibt es dafür keine Garantie (hast du 4 aufeinanderfolgende Elemente, die zu mergen wären, wird das Letzte übersehen werden). Natürlich kann man auch das flicken
iter2 = pClusterList->erase(iter2); if (iter2 == pClusterList->End()) break; --iter2; // iter2 kann an dieser Stelle nicht pClusterList->begin() seinWas davon zu halten ist, brauche ich hoffentlich nicht zu schreiben...
-
Ach du schande, hab ich voll übersehen. Ok dann wohl doch sofort mal mit deiner Lösung angefangen...
-
@camper,
ich dachte doch tatsächlich du hättest gerade ficken geschrieben. Zeit für Feierabend...
-
Ok hier der ganze Code wie er jetzt ist und auch funktioniert...
for (iter1 = pClusterList->begin(); iter1 != pClusterList->end(); iter1++) { pCi = *iter1; if ((pCi->pointList.size() < 1)) //|| (pCi->nType == nTypePedestrian)) continue; for (iter2 = iter1, ++iter2; iter2 != pClusterList->end(); ) { pCj = *iter2; if ((pCj->pointList.size() < 1) || (pCi == pCj)) { ++iter2; continue; } // Get closest point pair distance double fDistance = 1000; for (pointIter1 = pCi->pointList.begin(); pointIter1 != pCi->pointList.end(); pointIter1++) for (pointIter2 = pCj->pointList.begin(); pointIter2 != pCj->pointList.end(); pointIter2++) fDistance = min2 (fDistance, distanceXY(*pointIter1, *pointIter2)); if (fDistance > fMinDist) { ++iter2; continue; } // Merge clusters for (pointIter1 = pCj->pointList.begin(); pointIter1 != pCj->pointList.end(); pointIter1++){ pMi = (PointToTrack*) *pointIter1; pCi->addPoint(pMi); } // for pClusterList->erase(iter2++); delete pCj; } // for } // forDanke ncohmal an alle für die Hilfe