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

1

01.10.2009, 18:27

STL List Problem

Hallo ich hab ein Problem mit einer verketteten Liste..

Uns zwar hab ich eine Klasse WorldPlayers

WorldPlayers.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class WorldPlayers 
{
public:
    WorldPlayers(CL_NetGameClient *network_client,CL_GUIComponent *parent,CL_Font *font);
    ~WorldPlayers();

    void add_player(CPlayer *player);
    void rem_player(CPlayer *player);
    void update_player(CPlayer *player);
    bool get_player(CPlayer *player);
    void clear();
    void draw();

private:
    CL_NetGameClient *network_client;
    std::list<CPlayer*> players;
    CL_GUIComponent *parent;
    CL_Font *font;
};


WorldPlayers.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
WorldPlayers::WorldPlayers(CL_NetGameClient *network_client,CL_GUIComponent *parent,CL_Font *font)
{
    this->network_client = network_client;
    this->parent         = parent;
    this->font           = font;
}

WorldPlayers::~WorldPlayers()
{
    std::list<CPlayer*>::iterator i;
    for(i=this->players.begin(); i!= this->players.end(); i++)
    {
        delete((*i));
        (*i) = NULL;
    }
    this->players.clear();
}

void WorldPlayers::add_player(CPlayer *player)
{
    bool in_list = false;
    std::list<CPlayer*>::iterator i;
    for(i=this->players.begin(); i!= this->players.end(); i++)
    {
        if((*i)->charid == player->charid)
        {
            in_list = true;
        }
    }
    
    if(!in_list)
    {
        this->players.push_back(player);
    }
}

void WorldPlayers::rem_player(CPlayer *player)
{
    std::list<CPlayer*>::iterator i;
    for(i=this->players.begin(); i!= this->players.end(); i++)
    {
        if((*i)->charid == player->charid)
        {
            this->players.erase(i);
        }
    }
}

void WorldPlayers::update_player(CPlayer *player)
{
    std::list<CPlayer*>::iterator i;
    for(i=this->players.begin(); i!= this->players.end(); i++)
    {
        if((*i)->charid == player->charid)
        {
            (*i)->set_xpos(player->get_xpos());
            (*i)->set_ypos(player->get_ypos());
            (*i)->life = player->life;
            (*i)->current_frame = player->current_frame;
            (*i)->en = player->en;
        }
    }
}

bool WorldPlayers::get_player(CPlayer *player)
{
    std::list<CPlayer*>::iterator i;
    for(i=this->players.begin(); i!= this->players.end(); i++)
    {
        if((*i)->charid == player->charid)
        {
            return true;
        }
    }
    return false;
}

void WorldPlayers::clear()
{
    this->players.clear();
}

void WorldPlayers::draw()
{
    std::list<CPlayer*>::iterator i;
    for(i=this->players.begin(); i!= this->players.end(); i++)
    {
        (*i)->draw(this->parent->get_gc());
        this->font->draw_text(this->parent->get_gc(),((*i)->x_pos)-5,((*i)->y_pos)-5,(*i)->name,CL_Colorf::white);
    }
}

(Include aus Platzgründen weggelassen)

So innerhalb meine Spiel-Instanz würd nun eine neue Klasse davon erstellt und dann Spieler hinzugefügt ..

Wenn die Spieler den Server verlassen, sollen sie aus dieser Liste gelöscht werden.

Jedoch wenn dies passieren soll erhalt ich einen Fehler "list i is not incremetable" Also i kann nicht erhöht werden o.Ä also die Liste soll angeblich leer sein, was ja nicht der Fall ist..

Und ich weiß einfach nicht was ich falsch mache ...

Kann mir jemand da helfen ?

Wenn ich die Remove-Funktion rauslasse dann bleibt der Spieler weiter in dieser Liste enthalten..

Gruß,
xenus[/cpp]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

01.10.2009, 18:33

C-/C++-Quelltext

1
2
3
4
5
6
7
    for(i=this->players.begin(); i!= this->players.end(); i++) 
    { 
        if((*i)->charid == player->charid) 
        { 
            this->players.erase(i); 
        } 
    } 


Du löscht das Element und versucht dann (nach dem Schleifendurchgang im i++) auf den Nachfolger des gelöschten Elements zuzugreifen. Das kann natürlich nicht gut gehen (erase macht den iterator ungültig, da das Objekt ja futsch is).
Lösung: erase() gibt dir nen iterator auf den Nachfolger zurück:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
for(i=this->players.begin(); i!= this->players.end(); /* ! */ ) 
{ 
  if((*i)->charid == player->charid) 
  {
    it = this->players.erase(i);
  }
  else
    ++it;
}


Alternativ kannst du natürlich auch einfach die remove() Methode der list verwenden ;)

3

01.10.2009, 18:35

Achsooooo vielen dank, das klingt natürlich logisch hab ich gar nicht bedacht ;)

/edit

Ok jetzt krieg ich einen anderen Fehler ..

"list iterators incompatible" ..

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

01.10.2009, 18:36

Hab noch was editiert :roll:

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

5

01.10.2009, 18:37

Nach dem Aufruf von "erase" ist der Iterator ungültig, deshalb musst du den Iterator durch einen gültigen ersetzen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
void WorldPlayers::rem_player(CPlayer *player)
{
    std::list<CPlayer*>::iterator i;
    for(i=this->players.begin(); i!= this->players.end(); )
    {
        if((*i)->charid == player->charid)
        {
            i = this->players.erase(i); // neuzuweisung von i

        }
        else
            ++i;        
    }
} 


Da charid vermutlich einmalig ist kannst du die schleife aber auch einfach an dieser Stelle abbrechen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
void WorldPlayers::rem_player(CPlayer *player)
{
    std::list<CPlayer*>::iterator i;
    for(i=this->players.begin(); i!= this->players.end(); i++)
    {
        if((*i)->charid == player->charid)
        {
            this->players.erase(i);
            break; // raus aus der schleife

        }
    }
} 


Edit: hm... :)

6

01.10.2009, 18:42

Ah ok David_pb dein Tipp war der erfolgreiche ;)

Jetzt funktioniert es wie es soll, danke schön..

Achso ich hab da mal noch ne Frage denke das gehört fast auch zur List

Wenn ich mein Programm starte .. bekomm ich manchmal den Fehler

"vector out of submit range" also müsste ja irgendein Vektor außerhalb seines Bereiches sein was mich aber irgendwie wundert..

/edit

Dazu steht dann noch was von Debug Assertation .. ich arbeite mit VC2008 falls das was hilft

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

7

01.10.2009, 18:44

Zitat von »"xenus"«

seines Bereiches sein was mich aber irgendwie wundert..


Kann vorkommen. Interessant wär die Stelle und der Inhalt des vectors.

8

01.10.2009, 18:46

Das Problem ist wie krieg ich das raus ^^

Weil ich an der Stelle wo es passiert eig. keinen Vektor direkt verwende ..

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

9

01.10.2009, 18:50

Schau dir den zugehörigen Callstack an.

10

01.10.2009, 18:50

Ok da muss ich erstmal googlen wie ich den finde.. damit hab ich mich noch nie so richtig beschäftigt ^^

Werbeanzeige