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

Korowai

unregistriert

1

20.09.2016, 22:03

Vector Element löschen

Hi,

eine Frage zu den vectors.

Ich habe von einen class vector.

Diesen durchlaufe ich mit einer for Schleife:

C-/C++-Quelltext

1
2
3
for (int x=0;x<Arsenal0Element.size()-1;x++)
{...
}


In der Schleife soll das vector Element [x], wenn es eine if Bedingung erfüllt, gelöscht werden.

Naturgemäß durchläuft der vector seine Elemente (n) von Anfang bis Ende (0) bis (n-1).

Frage 1:
Wie lösche ich mit erase?

FRage 2:
Die Schleife überspringt, da ja ein Element gelöscht wird, doch das nächste, da dieses ja an die STelle des gelöschten tritt. Verstehe ich das richtig und was kann ich tun, um das zu verhindern?

Danke

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

3

20.09.2016, 22:22

Deine Schleife ignoriert aber das letzte Element... Aber naja, an sich ist es sinnvoll hierbei Iteratoren zu verwenden. So einen Iterator kannst du dir wie einen Zeiger vorstellen und er tut gut daran, sich eben genauso zu verhalten. Sehr nützliche Dinger. :)
Durch das moderne C++ reicht es aus folgendes zu schreiben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for(auto it = vector.begin(); it != vector.end(); )
{
    auto& currentElement = *it;

    if(currentElement.gone) // Irgendeine Bedingung, die mit dem Element zutun hat
    {
        it = vector.erase(it); // Objekt aus Container entfernen
        // Rückgabewert: Der Iterator *nach* dem Element, dass gelöscht wurde
    }
    else
    {
        ++it; // Den Iterator auf das nächste Element schieben
    }
}

Ansonsten musste man eben immer std::vector<MeineKlasse>::iterator it ausschreiben.

Korowai

unregistriert

4

20.09.2016, 22:27

Hi,

danke für die Antworten.

Habe gerade auch noch etwas überlegt. Würde es nicht Sinn machen, den Vektor von Ende her zu durchlaufen? Dann verschieben sich etwaig mittlere Elemente und verkleinern den Vektor, aber man ist in der Schleife ja bereits an einem niedrigeren Element als den zuletzt gelöschten...

Korowai

unregistriert

5

20.09.2016, 22:29

Hmm,

Checkmate, danke, Iteratoren beherrsche ich leider noch nicht. Sollte ich mir als nächstes ansehen. Grundlagen macht immer Sinn ;)

Danke David, Google hatte ich bereits bemüht, DEin Suchvorschlag ist allerdings genauer und besser als meiner...

Korowai

unregistriert

6

21.09.2016, 06:54

Hi Checkmateing,

// auto& currentElement = *it; --------- Ist mir unklar, wozu ich den Zeiger benötige

// if(currentElement.gone)

Wozu brauche ich diesen Zeiger? Reicht es nicht so?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
for (auto it=Arsenal0Element.begin(); it!=vector.end())
           {
                if (// Bedingung Element direkt löschen erfüllt)
                        {
                            it=vector.erase(it)
                            continue;
                        }
                else if (// Bedingung Element direkt löschen ebenfalls erfüllt)
                        {
                            it=vector.erase(it)
                            continue;
                        }       
                else if (// Bedingung Element löschen nachdem Code erfolgt)
                        {
                            //code
                            it=vector.erase(it)
                            continue;
                        };
                         
                ++it;
                }


Ich muss, glaube ich, nochmal präzisieren, dass der Vector komplett durchlaufen werden soll, und explizit in jeder Bedingung eine Löschung des aktuellen Elements erfolgt, nachdem Code ausgeführt wird und die Attribute des Vector Objekts auf andere Variablen übertragen werden. Der Vector soll in jedem Fall komplett durchlaufen werden.


Kann ich das so wie oben beschrieben machen?

Korowai

unregistriert

7

21.09.2016, 06:59

Zusatz:

Ich glaube, ich habe das jetzt gerade mit dem Zeiger ansatzweise verstanden. Wäre schön, jemand hilft mir mal auf die Sprünge, wie ich mir das aneignen kann? Meine Bücher sind da nicht so ergiebig glaube ich. Aber ich schaue mal im c++ Programmierer von Breymann...

Danke,

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

8

21.09.2016, 08:09

Das ist kein Zeiger, sondern eine Dereferenzierung. Der *-Operator des Iterators ist überladen. Der Iterator selbst ist praktisch gesehen nur ein Zeiger, der über die Elemente des Containers wandert. Mit *it bekommst du dann das eigentliche Element. Du brauchst da auch keine continue Statements. Einfach das ++it; in einen else-Block setzen und fertig.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

21.09.2016, 08:36


Ich glaube, ich habe das jetzt gerade mit dem Zeiger ansatzweise verstanden. Wäre schön, jemand hilft mir mal auf die Sprünge, wie ich mir das aneignen kann? Meine Bücher sind da nicht so ergiebig glaube ich. Aber ich schaue mal im c++ Programmierer von Breymann...

Danke,

Wichtig ist halt dass die Grundlagen gut sitzen. C++ ist da recht technisch und am Anfang nicht immer ganz einfach. Anfang kann sich da je nachdem auch auf einen recht langen Zeitraum beziehen. Guck dir doch vielleicht das Kapitel zu Zeigern noch mal an. Was das Buch angeht, das ist soweit ganz gut, ist aber ein ordentlicher Brocken. Guck dass du wenn möglichst die aktuelle Auflage bekommst, die wurde wohl auf den 14er Standard upgedatet.
Zu deinem Problem. Iteratoren solltest du dir auf jeden Fall mal genauer ansehen. Was das ist wurde ja schon erklärt, wenn du dir aber ein paar Beispiele ansiehst wird das ganze vielleicht klarer. Ansonsten bietet ein std::vector die Funktion pop_back an mit welcher das letzte Element gelöscht werden kann. Was du machen kannst ist das aktuelle Element mit dem letzten zu tauschen und dann pop_back aufzurufen. Auch hier darfst du deinen Index, in deinem Fall x, nicht in jedem Durchlauf erhöhen sondern nur solange kein Element gelöscht wird. Das ist an sich das selbe Konzept wie im Code von Checkmateing, nur dass er eben den Iterator erhöht und nicht den Index.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

10

21.09.2016, 09:18

Nach dem jetzt einige Grundlagen vermittelt worden sind, was nie verkehrt ist, sage ich jetzt: Das vom TE gewünschte gibt es schon fertig -> http://en.cppreference.com/w/cpp/algorithm/remove
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

Werbeanzeige