Absturz bei Löschen innerhalb eines std::vector

Orthak

Mitglied
Hallo,
ich möchte eine Reihe von strings vergleichen die in dem selben vektor gespeichert sind. Mein bisheriger Ansatz sieht folgend aus:

Code:
	vector<PersStruct>::iterator I = Catalogs[activeCatalog].PersStruct.begin();
	int eraseCounter = 0;
	while(I != Catalogs[activeCatalog].PersStruct.end()) {
		for(vector<PersStruct>::iterator J = Catalogs[activeCatalog].PersStruct.begin(); J != Catalogs[activeCatalog].PersStruct.end(); ++J) {
			if(I->question.compare(J->question) == 0) {
				Catalogs[activeCatalog].PersStruct.erase(I);
				eraseCounter++;
			}
		}
		++I;
	}

Bei PersStruct handelt es sich um eine Struktur, verglichen wird der darin enthaltene std::string question.

Die Zeile "Catalogs[activeCatalog].PersStruct.erase(I)" verursacht nun den Absturz und ich weis leider nicht warum. Ich übergebe den Iterator der aktuellen Position in der ersten Schleife. Zusätzlich wird der eraseCounter (int) genau dann erhöht wenn der vergleich fehlt schlägt und nicht wenn sie identisch sind.

Würde das Program also nicht sowieso abstürzen löscht er alle Elemente außer den wirklich doppelten :(. "I->question.compare(J->question) == 0" schaut im Bezug auf die compare Funktion für mich richtig aus.

Bin für jeden Hinweis dankbar..
 
Sorry, aber meine Glaskugel ist gerade zur Reparatur ..... ;-]

Was für eine Meldung kommt denn beim Absturz
Gruß
Klaus
 
Stimmt, die Art der Fehlermeldung hätte ich erwähnen sollen :p.

Da ich Visual Studio installiert habe erscheint der Just-In-Time Debugger mit "Unbehandelte Win32-Außnahme in Programname [700]". Ich weis damit leider nicht soviel anzufangen.

Interessant ist noch, das die Iteratoren sich scheinbar überschreiben oder ich einen Gedankenfehler mache. Ich lasse mir aktuell testweise die beiden strings untereinander ausgeben. Sie sind durchgängig identisch (Iterator zeigt auf das selbe Element?) und der Absturz kommt genau an der Position an der das doppelte Element geprüft wird.
 
vermutlich wird das auch nicht gehen - habe ich zumindest auch noch nie versucht! Vermutlich zerschießt Du Dir den einen Iterator durch den anderen!

Es gibt eine sehr hilfreiche Website zu C++ - und speziell zur STL:
http://www.namespace-cpp.de/C++/kennen/stl.htm

Darin solltest Du mal stöbern!
Habe eben so auf die Schnelle folgendes gefunden
Code:
#include <algorithm>

template <class Container>
void sortiere_und_entferne_Dopplungen(Container& c)
{
  std::sort( c.begin(), c.end() );
  typename Container::iterator neuesEnde = std::unique( c.begin(), c.end() );
  c.erase( neuesEnde, c.end() );  
}

Sieht für mich so aus, dass erst alle Einträge sortiert werden, und dann die doppelten Einträge von hinten gelöscht werden!

Hoffe, es hilft Dir weiter!
Gruß
Klaus
 
Danke für den Tip mit der Seite.
Die dort vorgestellte Methode funktioniert im meinem Falle leider nicht. Ich nehme an c++ weis nicht wie es structs sortieren soll ("error: no match for 'operator<' in [...]") und die Doublettensuche setzt einen sortierten Container vorraus.

Ich werde selbst noch etwas dran arbeiten und eine Lösung hier posten (sofern ich eine mehr oder weniger performante finde ;)).
 
oops - sorry, vielleicht hätte ich es deutlicher betonen sollen :suspekt:

Das ist natürlich kein echter Code, den Du so 1:1 übernehmen kannst, sondern eine allgemeine Vorlage, wie es mit den einzelnen Containern (vector, list oder so) zu handhaben ist (also quasi 'ne Art Pseudocode)!

In Deinem Fall musst Du natürlich bspw. "<Container>" durch vector ersetzen usw.

Gruß
Klaus
 
Das ist mir bewusst, mein Code ist entsprechend angepasst. Trotzdem erhalte ich einen Wulst an Linkerfehlermeldungen aus denen ich die besagte Kanns-Nicht-Sortieren Problematik herauslese.
 
Hi.
oops - sorry, vielleicht hätte ich es deutlicher betonen sollen :suspekt:

Das ist natürlich kein echter Code, den Du so 1:1 übernehmen kannst
Doch, genau das ist es. Es ist eine Vorlage (Template) die man genau so verwenden kann welche für jeden STL Container funktioniert.

@Orthak: Dann definiere doch einen Komparator:
C++:
int persComp (const PersStruct& a, const PersStruct& b) {
  return a.question.compare(b.question);
}
Die Funktion übergibst du dann als 3. Parameter bei der std::sort Funktion.

Gruß
 
Ich merke schon, sich ausgiebiger mit der STL zu beschäftigen würde sich lohnen :rolleyes: ...

Folgendes Problem hab ich nun aber noch: Die ganze Funktionalität ist in einer Klasse gekapselt und dies fürt scheinbar zu einem weiteren Problem. Die Funktion sieht folgend aus:

Code:
bool PersManager::persComp (const PersStruct& a, const PersStruct& b) {
	if(a.question.compare(b.question) == 0)
		return false;
	return true;
}
(ich habs auch mit int statt bool versucht, ist vom Ergebnis her egal.)

Möchte ich nun diese Funktion benutzen erhalte ich folgende Fehlermeldung:
argument of type `int (PersManager:: )(const PersStruct&, const PersStruct&)' does not match `int (PersManager::* )(const PersStruct&, const PersStruct&)'

Mir ist nicht ganz klar was es hier mit dem Zeiger auf sich hat. Selbe Funktion in einem kleinen Testprogram funktioniert wie gewünscht.
 
Hi.

Wenn du die Vergleichsfunktion in einer anderen Klasse als Methode implementieren willst, dann mußt du sie als static definieren.

Und ein Komparator muss int zurückgeben, so wie die std::string::compare Methode auch.
\edit: Nein, da hab ich mich geirrt. Der Komparator muss einen bool zurückgeben. Und zwar sollte er true zurückgeben wenn der erste Parameter kleiner ist:
C++:
bool PersManager::persComp (const PersStruct& a, const PersStruct& b) {
	return a.question.compare(b.question) < 0;
}

Warum definierst du keine Halbordnung für die PersStruct Klasse (operator<)? Ein Komparator ist mehr sinnvoll, wenn du die Objekte in einem Kontainer mal anders sortieren willst als normalerweise.

Gruß

PS: Wenn du eine Fehlermeldung postest wäre es toll wenn du auch den dazugehörigen Code zeigst.
 
Zuletzt bearbeitet:
Zurück