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 :

parcourir une liste de la fin vers le début


Sujet :

SL & STL C++

  1. #1
    Membre habitué
    Avatar de zdra
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2002
    Messages : 164
    Points : 187
    Points
    187
    Par défaut parcourir une liste de la fin vers le début
    Bonjour,

    Voilà j'ai tenté ceci pour parcourir une stl::list de la fin au début:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    list<CObjectBase*>::iterator iter;
    for (iter = objectList.end(); iter != objectList.begin(); iter--)
    {
      ...
      if (...)
         objectList.erase(iter);
    }
    Apparement ce code me fait un jolie segfault. Comment faire alors ?

    Et aussi, dans cette boucle sous certaines conditions je suis amenté a supprimer iter de la liste mais je me demande si apres ça on peut continuer gentillement la boucle ?? ou ça risque aussi de provoquer des segfault ? Donc si ça risque de provoquer des miseres, comment faire ça ??

    Merci !
    This message was powered by:
    Ubuntu GNU/Linux

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2004
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique

    Informations forums :
    Inscription : Février 2004
    Messages : 35
    Points : 36
    Points
    36
    Par défaut
    dans le cas d'un iterator non reverse, l'iterator .end() pointe après le dernier element.
    Si tu veux parcourir ta liste dans le sens inverse tu doi utiliser un reverse iterator:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    list<CObjectBase*>::reverse_iterator iter; 
    for (iter = objectList.rbegin(); iter != objectList.rend(); iter++) 
    { 
      ... 
      if (...) 
         objectList.erase(iter); 
    } 
    [fais à la volée]

  3. #3
    Membre habitué
    Avatar de zdra
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2002
    Messages : 164
    Points : 187
    Points
    187
    Par défaut
    oké je connaissais pas. Merci.

    Cependant j'ai un autre probleme, apparement list::erase() n'est pas défini sur un revers_iterator.... Comment faire alors pour enlever des elements pendant le parcour ?
    This message was powered by:
    Ubuntu GNU/Linux

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2004
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique

    Informations forums :
    Inscription : Février 2004
    Messages : 35
    Points : 36
    Points
    36
    Par défaut
    Pourquoi dois-tu la parcourir dans le sens inverse?

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Attention à la fonction erase qui va invalider l'itérateur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    list<CObjectBase*>::reverse_iterator iter;
    for (iter = objectList.rbegin(); iter != objectList.rend(); )
    {
      ...
      if (...)
         iter = objectList.erase(iter);
      else
        ++iter;
    }
    Pour ce qui est d'erase + reverse_iterator, effectivement c'est un problème. Plusieurs solutions bourrins : récupérer l'indice de ton itérateur, puis faire avancer un iterator de size - indice à partir de begin. Ainsi tu pointeras sur le même élément mais avec un iterator. Ou encore inverser ta liste avant parcours puis la réinverser après.

    Il me semble qu'il existait des conversions automatiques entre les types d'itérateurs, il faudrait voir si dans ce cas ce ne serait pas possible.

  6. #6
    Membre habitué
    Avatar de zdra
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2002
    Messages : 164
    Points : 187
    Points
    187
    Par défaut
    En fait c'est pour une lib SDL_gui que je suis entriant de developper pour un jeu que je fais... Et donc la liste des objets doit etre affiché dans un sens, mais runnée dans l'autre sens car la derniere à etre affichée est la 1er a recevoir les messages de souris etc...

    Ce que je vais faire c'est inverser la liste une fois pour toutes et faire l'affichage avec des revers_iterator comme ça j'ai pas le probleme du erase

    Cela dit, d'un maniere ou de l'autre si l'iterator est invalidé apres un erase ça va merder.... je vais faire des testes pour voir si ça marche...
    This message was powered by:
    Ubuntu GNU/Linux

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    63
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 63
    Points : 77
    Points
    77
    Par défaut
    Pas sur que ce soit tres propre mais tu peux faire comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      list<int> test;
      test.push_back(5);
      test.push_back(6);
      test.push_back(7);  
      test.push_back(8);
      test.push_back(9);
     
      typedef list<int>::reverse_iterator iter;
      for(iter it = test.rbegin(); it != test.rend(); ++it) {
        if((*it) == 6)
          test.erase(--(it.base()));
      }

  8. #8
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Cela dit, d'un maniere ou de l'autre si l'iterator est invalidé apres un erase ça va merder....
    Ben suffit de gérer ça correctement, comme je te l'ai montré

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test.erase(--(it.base()));
    Bien vu ! C'est bien comme cela qu'on peut passer d'un reverse_iterator à un iterator. Maintenant je me souviens où j'avais vu ça : dans Effective STL, il y a un diagramme expliquant les relations entre les différents types d'itérateurs et comment passer de l'un à l'autre.

  9. #9
    Membre habitué
    Avatar de zdra
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2002
    Messages : 164
    Points : 187
    Points
    187
    Par défaut
    j'ai ptetre une idée, un truc comme ça:

    iter_next = iter + 1;
    objectList.erase(iter);
    iter = iter_next;

    Loulou24 > ici je vois que erase retourne void, donc ça marchera pas ton algo il me semble... je vais qd meme essayer
    This message was powered by:
    Ubuntu GNU/Linux

  10. #10
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Mauvaise doc

    http://www.sgi.com/tech/stl/List.html

    iterator erase(iterator pos)
    Erases the element at position pos.
    En ce qui concerne ta solution, l'opérateur + est reservé aux RandomAccessIterator (ceux des vector). Ici tu aurais dû utiliser ++.

  11. #11
    Membre habitué
    Avatar de zdra
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2002
    Messages : 164
    Points : 187
    Points
    187
    Par défaut
    oké c'est vrai que cette doc est plus complete

    Donc en combiant les 2solus ça donne ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    list<CObjectBase*>::reverse_iterator iter;
    for (iter = objectList.rbegin(); iter != objectList.rend(); )
    {
      ...
      if (...)
         iter = objectList.erase(--(iter.base()));
      else
        ++iter;
    }
    Comme ça pas de risque que iter soit invalidé, et avec le ptit truc du --(iter.base()) on peut erase() un reverse_iterator

    Merci !

    [edit] sauf que erase ne retourne retourne pas un reverse_iterator, mais un iterator....
    This message was powered by:
    Ubuntu GNU/Linux

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    La conversion inverse est possible également : les reverse_iterator possèdent un constructeur (explicite) qui leur permet de se construire à partir d'un iterator.

    Mais bon, après tant de bidouilles, la solution qui me parait la plus propre, simple et performante était ta première idée :
    Ce que je vais faire c'est inverser la liste une fois pour toutes et faire l'affichage avec des revers_iterator comme ça j'ai pas le probleme du erase

  13. #13
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Loulou, l'article dont tu parles dans effective STL est aussi disponible en ligne : http://www.aristeia.com/Papers/CUJ_June_2001.pdf
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 03/08/2008, 20h24
  2. Parcourir une liste à partir de la fin
    Par phfle1 dans le forum VB.NET
    Réponses: 2
    Dernier message: 04/06/2008, 21h11
  3. Parcourir une liste de checkbox
    Par fet dans le forum ASP
    Réponses: 3
    Dernier message: 25/07/2006, 12h35
  4. Parcourir une liste deroulante
    Par brandon dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 17/02/2005, 19h03
  5. [langage] Parcourir une list de array
    Par nledez dans le forum Langage
    Réponses: 4
    Dernier message: 08/11/2004, 17h11

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