Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Teiby

Frischling

  • »Teiby« ist der Autor dieses Themas

Beiträge: 42

Beruf: Ausbildung

  • Private Nachricht senden

1

23.10.2011, 14:48

Werte (sicher) aus Listen löschen

Ich hab da ein kleines Problem mit Listen, die mir das Programm abschmieren lassen.

Und zwar möcht ich aus einer Struktur einen Wert raussuchen, und wenn der gefunden wurde, den löschen.

Das sieht bisher so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
if(!Spielerliste.empty())
    for (std::list<S_Spieler>::iterator i = Spielerliste.begin(); i != Spielerliste.end(); ++i)
        if(i->Guid == GUID)
        {               
            Spielerliste.erase(i);

            if(Spielerliste.empty())
                break;
        }


Wenn aber nun mehr als ein Werte dort gespeichert sind, schmiert das Programm ab. Ohne die empty Abfrage, kann man nichtmal ein Wert löschen. Es gibt also Probleme mit dem Schleifenanfang. Kenn aber leider keinen Rat wie man das richtig macht...
Im Buch "C++ für Spieleprogrammierer" stehen nur paar Beispiele mit "Einzelwerte" drin. Also keine Strukturen...

Ich hoffe ihr könnt mir da weiterhelfen und danke schonmal :>

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Teiby« (23.10.2011, 14:56)


NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

2

23.10.2011, 15:58

es ist egal ob du strukturen oder eingebaute Datentypen verwendest.
Du kannst den Iterator nicht weiterverwenden, wenn du damit gelöscht hast.
probiers mal mit:

C-/C++-Quelltext

1
i = Spielerliste.erase(i); // erase gibt den iterator aufs nächste element zurück

das:

C-/C++-Quelltext

1
2
if(Spielerliste.empty())
      break;

kannst du dir sparen.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

3

23.10.2011, 17:16

Du könntest remove_if verwenden, das wäre IMO die eleganteste variante:

http://www.cplusplus.com/reference/algorithm/remove_if/

Wenn du nur ein Element löschen möchtest könntest du auch find + erase benuten.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

23.10.2011, 19:27

Schau dir mal an was std::list::erase() für einen Rückgabewert hat ;)

Teiby

Frischling

  • »Teiby« ist der Autor dieses Themas

Beiträge: 42

Beruf: Ausbildung

  • Private Nachricht senden

5

24.10.2011, 16:11

C-/C++-Quelltext

1
i = Spielerliste.erase(i);

funktioniert leider nicht.

die idee mit remove_if ist gut, aber leider kann ich dies nicht verwenden, da in der schleife noch werte abgefragt werden bevor gelöscht wird.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

24.10.2011, 16:35

C-/C++-Quelltext

1
i = Spielerliste.erase(i);

funktioniert leider nicht.

Doch. Das ++i darfst du dann natürlich nicht machen.

die idee mit remove_if ist gut, aber leider kann ich dies nicht verwenden, da in der schleife noch werte abgefragt werden bevor gelöscht wird.

Wo liegt das Problem?

Teiby

Frischling

  • »Teiby« ist der Autor dieses Themas

Beiträge: 42

Beruf: Ausbildung

  • Private Nachricht senden

7

24.10.2011, 17:03

Zitat

Wo liegt das Problem?
Also wenn ich das richtig verstanden hab, gibt man dem eine bool Funktion "mit" die dann bei jedem Wert durchlaufen wird. Kann ich dann der bool Funktion auch noch Werte mitgeben? In dem Beispiel auf http://www.cplusplus.com/reference/algorithm/remove_if/ wird ja nur die Funktion ohne Wert weitergebeben...


Zitat

Das ++i darfst du dann natürlich nicht machen.
Hört sich logisch an. Muss ich aber nun das ++i aus der "Schleifen-Start" ausbauen und mitten in die schleife machen. Das funktioniert nun auch wunderbar. Danke :)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

24.10.2011, 17:25

remove_if funktioniert mit allem was aufrufbar ist. Das muss nicht unbedingt eine Funktion sein. Kann z.B. auch ein Funktor sein. Wenn dein Compiler schon Lambdas kann, wirds sogar trivial:

C-/C++-Quelltext

1
2
3
  Spielerliste.remove_if([=](const S_Spieler& spieler) {
    return spieler.Guid == GUID;
  });

Teiby

Frischling

  • »Teiby« ist der Autor dieses Themas

Beiträge: 42

Beruf: Ausbildung

  • Private Nachricht senden

9

24.10.2011, 17:52

Lambdas gibts ja erst seit 2 Monaten. Also nein funktioniert bei mir damit nicht. Aber danke für die Info :>

Bei der remove_if Funktion muss man eben nun extra ne Funktion schreiben und deshalb sieht man dann nicht sofort was die remove_if löscht. Find ich etwas unpraktisch.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

24.10.2011, 18:01

Also mein Compiler (Visual C++) unterstützt Lambdas schon seit bald 2 Jahren ;)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (24.10.2011, 18:07)


Werbeanzeige