IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

Suppression d'un élément d'une list


Sujet :

SL & STL C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 21
    Points : 12
    Points
    12
    Par défaut Suppression d'un élément d'une list
    Je ne suis pas un expert en C++ et mon problème est le suivant :

    J'ai une classe qui contient une liste de pointeurs (list<Ant*> colony) et lorsque je veux supprimer un de ces pointeurs avec la fonction remove ça plante.

    La méthode en question :
    void Environment::killAnt(Ant*& antTokill){
    colony.erase(antToKill);
    }

    Si quelqu'un a une solution pour ce problème je suis preneur, merci.

  2. #2
    Membre éclairé

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Points : 858
    Points
    858
    Par défaut
    Regarde le prototype de la fonction list::erase(), il prend un itérateur, pas un pointeur.

  3. #3
    Membre actif
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Points : 216
    Points
    216
    Par défaut
    donc il faut : créer un itérateur list<...>::iterator iter qui commence a maListe.begin(), le faire parcourir la liste des fourmis.

    Si l'iterateur pointe sur la fourmi à detruire, alors faire erase(iter)
    sinon continuer la boucle avec ++iter.

  4. #4
    Membre actif
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Points : 216
    Points
    216
    Par défaut
    Ah oui, une chose à rajouter aussi :

    un erase supprime le pointeur de la liste, mais en aucun cas ne détruit l'objet pointé, s'il a été crée dynamiquement avec new. Tu dois faire un delete toi meme avant(ou après) avoir fait erase.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 21
    Points : 12
    Points
    12
    Par défaut
    Merci, j'ai modifié ma fonction et j'ai toujours des problèmes de segmentation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void Environment::killAnt(Ant*& antToKill){
             list<Ant*>::iterator it;
             for (it=colony.begin();it!=colony.end();it++) {
                 Ant* a = (Ant*) (*it);
                 if(a==antToKill){
                   colony.erase(it);
                   delete(antToKill);
                 }
             }
    }
    Des idées ?

  6. #6
    Membre actif
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Points : 216
    Points
    216
    Par défaut
    (utilises la balise code stp ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void Environment::killAnt(Ant*& antToKill){
      list<Ant*>::iterator it;
      for (it=colony.begin();it!=colony.end();it++) {
        Ant* a = (Ant*) (*it);
        if(a==antToKill){
            colony.erase(it);
            delete(antToKill);
        }
      }  
    }
    il ne faut pas caster *it en Ant*, c'est deja un Ant* (de plus il faut éviter le cast style C en C++ et lui préférer le static_cast() ou le dynamic_cast(), mais c'est un autre problème)

    ici if ((*it) == antToKill) suffit., je pense. ça reste clair.

    en suite c'est delete antToKill, pas delete(antToKill).

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 21
    Points : 12
    Points
    12
    Par défaut
    Pour delete c'était une faute de frappe comme je ne travaille pas sur le PC sur lequel je suis connecté à Internet.

    J'ai modifié un peu la structure du programme, la fonction killAnt est passée à la trappe et j'ai donc la fonction scheduleAnts(). Ca compile mais la partie rouge pose encore des problèmes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void Environment::scheduleAnts(){
         if (!colony.empty()) {
            list<Ant*>::iterator it;
            for (it=colony.begin();it!=colony.end();it++) {
                 Ant* a = (*it);
                 if(!a->live()){
                 colony.erase(it);
                 delete *it;
                 nbAnts--;
                 }                                 
            }        
        }
    }
    Merci encore

  8. #8
    Membre actif
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Points : 216
    Points
    216
    Par défaut
    il faut faire delete a et non delete it car une fois que tu as supprimé l'élément "pointé" (je devrais dire "itéré") par it, it devient alors, bien évidemment, invalide (*it a été supprimé de la liste ! donc it ne doit pas permettre d'accéder à un élément qui n'est plus dans le conteneur). C'est une sorte de pointeur qui pointe sur le pointeur Ant* correspondant.

    ou alors faire le delete it avant que le it soit devenu invalide, c'est-à-dire avant le erase.

    Dis nous si ton code pose toujours des problèmes.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 21
    Points : 12
    Points
    12
    Par défaut
    Si on remplace *it par a et quelque soit la position du delete par rapport au erase, ça ne règle malheureusement pas le problème.

    Je ne vois pas trop où ça coince là parce qu'il n'y a que cette portion qui pose problème.

  10. #10
    Membre actif
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Points : 216
    Points
    216
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void Environment::scheduleAnts(){
         if (!colony.empty()) {
            list<Ant*>::iterator it;
            for (it=colony.begin();it!=colony.end();it++) {
                 Ant* a = (*it);
                 if(!a->live()){
                     delete a;
                     colony.erase(it);
                     nbAnts--;
                 }                                 
            }        
        }
    }
    Tu as un débugger pour pouvoir dire à quelle ligne le problème apparait ? delete a appelle le destructeur de ton objet Ant, peut-e^tre y'a t-il des soucis ici.

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 21
    Points : 12
    Points
    12
    Par défaut
    Mon débuggeur me balance une erreur de segmentation au niveau de la déclaration de a. c'est bizarre parce que la méthode live() est exécutée sans problème si la partie en rouge ne l'est pas.

    Sinon le destructeur de Ant met seulement un pointeur à NULL.

  12. #12
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    bonjour. erase invalid it..
    donc il faut récupere un iterateur valid
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    void Environment::scheduleAnts(){
         if (!colony.empty()) {
            list<Ant*>::iterator it;
            for (it=colony.begin();it!=colony.end();) {
                 Ant* a = (*it);
                 if(!a->live())
                     {
                     delete a;
                     it =colony.erase(it);
                     nbAnts--;
                     }        
                else
                    {
                    ++it;
                     }                         
            }        
        }
    }
    http://cpp.developpez.com/faq/cpp/?p...ssion_elements

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 21
    Points : 12
    Points
    12
    Par défaut
    Ok, ça tourne nickel maintenant. Merci

  14. #14
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Avec les algorithm, ca donnerai un truc comme ca


    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void Environment::scheduleAnts()
    {
       if (colony.empty()) return;
       list<Ant*>::iterator  itend = colony.end();
       list<Ant*>::iterator  itremove=std::partition(colony.begin(),itend ,mem_fun( Ant::live() );
       list<Ant*>::iterator  it = itremove;
       while(it!=itend )
          {
          delete *it;
          ++it;
          nbAnts--;
          }
       colony.erase(itremove,itend );
    }
    Je n'utilise pas l'algo remove car ce sont des pointeur qui sont stocké

    Pour les algo
    http://r0d.developpez.com/articles/algos-stl/

  15. #15
    Membre actif
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Points : 216
    Points
    216
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    bonjour. erase invalid it..
    donc il faut récupere un iterateur valid
    arf oui en effet ! C'est vrai que la boucle continuait avec it++ du for après la destruction...

    On pourrait aussi, dans la mesure ou il n'y a jamais deux fois le meme pointeur fourmi dans la liste, faire directement un break; après avoir détruit et supprimé l'élément, mais c'est bien moins élégant.

  16. #16
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Pacorabanix Voir le message
    arf oui en effet ! C'est vrai que la boucle continuait avec it++ du for après la destruction...

    On pourrait aussi, dans la mesure ou il n'y a jamais deux fois le meme pointeur fourmi dans la liste, faire directement un break; après avoir détruit et supprimé l'élément, mais c'est bien moins élégant.
    ben non il restera des fourmis morte

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [PHP 5.4] Suppressions des lignes/éléments d'une liste
    Par aspkiddy dans le forum Langage
    Réponses: 6
    Dernier message: 10/04/2014, 18h48
  2. Suppression d'un élément d'une List
    Par cedric774 dans le forum C#
    Réponses: 7
    Dernier message: 27/02/2011, 17h09
  3. Suppression d'un élément dans une liste chainée
    Par jbarreau-mainson dans le forum Débuter
    Réponses: 1
    Dernier message: 06/05/2009, 15h49
  4. Suppression d' éléments dans une liste.
    Par conan76 dans le forum ASP.NET
    Réponses: 3
    Dernier message: 02/03/2007, 09h33
  5. Réponses: 8
    Dernier message: 01/04/2006, 10h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo