Newsgroup: it.comp.lang.c++
Titolo: Liste e rimozione elementi [lungo]

Ciao a tutti,
vi chiedo un aiuto su un problema che mi tedia da un po':
ho due classi
///////////////////////////////////////////////////////////
class player
{
public:
 uint32 player_id;
[...]
};
class team
{
public:
 uint32 team_id;
 [...]
};
///////////////////////////////////////////////////////////
e due liste:
///////////////////////////////////////////////////////////
list<team> teamList;
list<player> playerTotalList;
///////////////////////////////////////////////////////////
Popolo le liste correttamente, per lo meno senza avere errori, mentre quando 
si tratta di cancellare elementi, cominciano i problemi. Per la lista di 
Player le cose vanno via lisce:
///////////////////////////////////////////////////////////
bool erasePlayerFromId(uint32 id, list<player> &playerList)
{
 list<player>::iterator ItPlayer;
 for(ItPlayer=playerList.begin();ItPlayer != playerList.end();)
 {
   if (ItPlayer->player_id == id)
   {
    ItPlayer=playerList.erase(ItPlayer);
   }
   else
   {
    ItPlayer++;
   }
 }
 return false;
 }
///////////////////////////////////////////////////////////
Mentre per la lista team, le cose si complicano:
///////////////////////////////////////////////////////////
bool eraseTeamFromId(uint32 id, list<team> &teamListVar)
{
    list<team>::iterator ItTeam;
 for(ItTeam=teamListVar.begin(); ItTeam != teamListVar.end();)
 {
  if (ItTeam->team_id==id)
  {
     ItTeam = teamListVar.erase(ItTeam);
  }
  else
  {
      ItTeam++;
  }
 }
 return false;
}
///////////////////////////////////////////////////////////
Potrete facilmente notare come le due funzioni si assomiglino (sono 
praticamente uguali), ma quando tento di cancellare dalla lista di Team per 
più di una volta la lista va a farsi benedire e tutto crasha.
L'errore potrebbe essere altrove, ma debuggando ho visto che gli oggetti 
vengono istanziati correttamente prima di essere collocati nelle rispettive 
liste, e le due funzioni di erase vengono invocate con i parametri corretti 
(con l'id da eliminare e con teamList e playerTotalList rispettivamente).
Come dicevo, l'errore potrebbe essere altrove, però ho paura di essermi 
perso qualcosa sulle liste e soprattutto sulla funzione di erase.
Riporto qua sotto le classi complete,
Grazie,
^A^
///////////////////////////////////////////////////////////
 #include <list>
using namespace std;
class team;
class player
{
public:
 uint32 player_id;
 string player_name;
 uint32 player_team;
 uint32 points;
 uint32 points_sent;
 player();
 player(uint32 new_id,string new_name,uint32 new_team);
};
class team
{
public:
 uint32 team_id;
 string team_name;
 uint32 team_captain;
 list<uint32> team_playerList;
 team(player *player, string name);
 team(list<player>::iterator ItPlayer, string name);
 void addPlayer(player new_player);
 player getCaptain();
};
///////////////////////////////////////////////////////////

 perso qualcosa sulle liste e soprattutto sulla funzione di erase.
Ti sei dimenticato di leggere attentamente la documentazione di tale 
funzione.
Eccola qui sotto:
list::erase
===========
   iterator erase(iterator where);
   iterator erase(iterator first, iterator last);
The first member function removes the element of the controlled sequence 
pointed to by where. The second member function removes the elements of 
the controlled sequence in the range [first, last). Both return an 
iterator that designates the first element remaining beyond any elements 
removed, or end() if no such element exists.
Erasing N elements causes N destructor calls. Reallocation occurs, so 
iterators and references become invalid for the erased elements.
The member functions never throw an exception.
-- 
     Carlo Milanesi
 
http://digilander.libero.it/carlmila

Anghel wrote:
 > vi chiedo un aiuto
 > Per la lista di Player le cose vanno via lisce:
Per caso.
 > Mentre per la lista team, le cose si complicano:
Non e' che si complicano, infatti il codice e' analogo, ma il difetto 
genera un malfunzionamento.
 > ho paura di essermi perso qualcosa sulle liste e soprattutto sulla 
funzione di erase.
Ti sei dimenticato di leggere attentamente la documentazione di tale 
funzione. Per esempio:
http://www.dinkumware.com/manuals/reader.aspx?b=p/&h=list.html#list::erase
Tradotto in italiano, hai usato un iteratore non piu' valido. Invece 
avresti dovuto assegnare all'iteratore il valore reso da "erase".


     
http://digilander.libero.it/carlmila
Ciao e grazie,
A 

 cervello :)
Chiedo umilmente scusa per aver dato un consiglio inappropriato.
Il tuo codice era corretto (almeno quello in erasePlayerFromId e 
eraseTeamFromId). Mi ha fuorviato l'uso del "for", che non e' opportuno 
per tale operazione.
Comunque non saprei dove si annida il baco del tuo programma; suppongo 
altrove (cioe' prima), e solo in quel momento si fa sentire.
Avrei pero' delle altre obiezioni sul tuo codice.
* Sia per team che per player, se l'id e' una chiave univoca, sarebbe 
meglio usare una struttura "map".
* Le due funzioni rendono sempre "false".
* Gli unici modi di creare un team sono usando un puntatore a un player, 
o un iteratore in una lista di player. Ma penso che possano esistere 
team che non hanno ancora nessun player.
* Si puo' creare un team senza specificare il suo id.


     
http://digilander.libero.it/carlmila
^A^