erase entre un list::iterator et un list:reverse_iterator ???
2 réponses
Aurélien Barbier-Accary
Tout est dans le titre...
Mais tout d'abord bonjour !
Je souhaite supprimer un ensemble d'objets contenus dans une liste doublement
chaînée. Pour trouver les bornes de suppression, je parcours la liste dans les
deux sens et j'utilise (donc) un itérateur normal et un itérateur inversé.
Mon souci est que je ne peux pas utiliser directement ces itérateurs pour faire
un erase :-(
Voici en code schématiquement mon pb :
list<T>::iterator it;
list<T>::reverse_iterator rit;
bool ok = false;
for(it = ++maliste.begin(); (!ok) && (it!= maliste.end()); it++)
[... -> ok=true ...]
ok = false;
for(rit = ++maliste.rbegin(); (!ok) && (rit!= maliste.rend()); rit++)
[... -> ok=true ...]
// Rq: je suis sûr que it et rit ne se croisent pas !
maliste.erase(it,rit);
Comment faire pour obtenir deux itérateurs de même type à partir de it et de rit ?
Merci d'avance pour vos conseils.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Aurélien Barbier-Accary
maliste.erase(it,(++rit).base()); J'ai bon ?! :-)
Pour ceux qui se demandent, j'ai lu que maliste.erase(it,--rit.base()); pouvait ne pas compiler avec certains compilateurs pour des vecteurs et des string (à la place d'une liste). Pour la doc de la fonction base(), voir http://www.sgi.com/tech/stl/ReverseIterator.html
-- Aurélien Barbier-Accary
maliste.erase(it,(++rit).base());
J'ai bon ?! :-)
Pour ceux qui se demandent, j'ai lu que maliste.erase(it,--rit.base()); pouvait
ne pas compiler avec certains compilateurs pour des vecteurs et des string (à la
place d'une liste).
Pour la doc de la fonction base(), voir
http://www.sgi.com/tech/stl/ReverseIterator.html
Pour ceux qui se demandent, j'ai lu que maliste.erase(it,--rit.base()); pouvait ne pas compiler avec certains compilateurs pour des vecteurs et des string (à la place d'une liste). Pour la doc de la fonction base(), voir http://www.sgi.com/tech/stl/ReverseIterator.html
-- Aurélien Barbier-Accary
kanze
Aurélien Barbier-Accary wrote:
Tout est dans le titre...
Je souhaite supprimer un ensemble d'objets contenus dans une liste doublement chaînée. Pour trouver les bornes de suppression, je parcours la liste dans les deux sens et j'utilise (donc) un itérateur normal et un itérateur inversé. Mon souci est que je ne peux pas utiliser directement ces itérateurs pour faire un erase :-(
Voici en code schématiquement mon pb : list<T>::iterator it; list<T>::reverse_iterator rit; bool ok = false; for(it = ++maliste.begin(); (!ok) && (it!= maliste.end()); it++) [... -> ok=true ...] ok = false; for(rit = ++maliste.rbegin(); (!ok) && (rit!= maliste.rend()); rit++) [... -> ok=true ...] // Rq: je suis sûr que it et rit ne se croisent pas ! maliste.erase(it,rit);
Comment faire pour obtenir deux itérateurs de même type à partir de it et de rit ?
Il faudrait extraire la base de l'itérateur inverse. Ensuite, il faudrait lui appliquer des corrections, selon que l'élément trouvé doit en faire partie des éléments extraits ou non. (Selon le cas, il pourrait aussi falloir une correction à l'itérateur normal.)
Attention aussi ! Dans ton exemple, tu pourrais facilement rencontrer un comportement indéfini. Mieux vaut utiliser l'itérateur trouvé dans la première boucle comme itérateur d'end de la deuxième. Quelque chose du genre :
typedef list<T> List ; typedef List::iterator Iter ;
Iter bottom = std::find_if( l.begin(), l.end(), bottomCondition ) ; if ( bottom == l.end() ) { // Non trouvé, que faire (une exception, peut-être) } Iter top = std::find_if( l.rbegin(), List::reverse_iterator( bottom ), topCondition ).base() ; if ( top == bottom ) { // Non truové... } if ( ! conditionsInclusives && top != bottom ) { -- top ; // se positionne sur le dernier élément if ( top != bottom ) { ++ bottom ; // et au delà du premier élément, } // pour ne pas les effacer. } l.erase( bottom, top ) ;
Reste la question de ce que tu veux faire si les récherches échouent. (Le code ici n'efface rien dans ce cas-là. Encore que c'est à vérifier -- je ne me suis pas penché trop sur les conditions limites.)
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aurélien Barbier-Accary wrote:
Tout est dans le titre...
Je souhaite supprimer un ensemble d'objets contenus dans une
liste doublement chaînée. Pour trouver les bornes de
suppression, je parcours la liste dans les deux sens et
j'utilise (donc) un itérateur normal et un itérateur inversé.
Mon souci est que je ne peux pas utiliser directement ces
itérateurs pour faire un erase :-(
Voici en code schématiquement mon pb :
list<T>::iterator it;
list<T>::reverse_iterator rit;
bool ok = false;
for(it = ++maliste.begin(); (!ok) && (it!= maliste.end()); it++)
[... -> ok=true ...]
ok = false;
for(rit = ++maliste.rbegin(); (!ok) && (rit!= maliste.rend()); rit++)
[... -> ok=true ...]
// Rq: je suis sûr que it et rit ne se croisent pas !
maliste.erase(it,rit);
Comment faire pour obtenir deux itérateurs de même type à
partir de it et de rit ?
Il faudrait extraire la base de l'itérateur inverse. Ensuite, il
faudrait lui appliquer des corrections, selon que l'élément
trouvé doit en faire partie des éléments extraits ou non. (Selon
le cas, il pourrait aussi falloir une correction à l'itérateur
normal.)
Attention aussi ! Dans ton exemple, tu pourrais facilement
rencontrer un comportement indéfini. Mieux vaut utiliser
l'itérateur trouvé dans la première boucle comme itérateur d'end
de la deuxième. Quelque chose du genre :
typedef list<T> List ;
typedef List::iterator Iter ;
Iter bottom = std::find_if( l.begin(), l.end(),
bottomCondition ) ;
if ( bottom == l.end() ) {
// Non trouvé, que faire (une exception, peut-être)
}
Iter top = std::find_if( l.rbegin(),
List::reverse_iterator( bottom ),
topCondition ).base() ;
if ( top == bottom ) {
// Non truové...
}
if ( ! conditionsInclusives && top != bottom ) {
-- top ; // se positionne sur le dernier élément
if ( top != bottom ) {
++ bottom ; // et au delà du premier élément,
} // pour ne pas les effacer.
}
l.erase( bottom, top ) ;
Reste la question de ce que tu veux faire si les récherches
échouent. (Le code ici n'efface rien dans ce cas-là. Encore que
c'est à vérifier -- je ne me suis pas penché trop sur les
conditions limites.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Je souhaite supprimer un ensemble d'objets contenus dans une liste doublement chaînée. Pour trouver les bornes de suppression, je parcours la liste dans les deux sens et j'utilise (donc) un itérateur normal et un itérateur inversé. Mon souci est que je ne peux pas utiliser directement ces itérateurs pour faire un erase :-(
Voici en code schématiquement mon pb : list<T>::iterator it; list<T>::reverse_iterator rit; bool ok = false; for(it = ++maliste.begin(); (!ok) && (it!= maliste.end()); it++) [... -> ok=true ...] ok = false; for(rit = ++maliste.rbegin(); (!ok) && (rit!= maliste.rend()); rit++) [... -> ok=true ...] // Rq: je suis sûr que it et rit ne se croisent pas ! maliste.erase(it,rit);
Comment faire pour obtenir deux itérateurs de même type à partir de it et de rit ?
Il faudrait extraire la base de l'itérateur inverse. Ensuite, il faudrait lui appliquer des corrections, selon que l'élément trouvé doit en faire partie des éléments extraits ou non. (Selon le cas, il pourrait aussi falloir une correction à l'itérateur normal.)
Attention aussi ! Dans ton exemple, tu pourrais facilement rencontrer un comportement indéfini. Mieux vaut utiliser l'itérateur trouvé dans la première boucle comme itérateur d'end de la deuxième. Quelque chose du genre :
typedef list<T> List ; typedef List::iterator Iter ;
Iter bottom = std::find_if( l.begin(), l.end(), bottomCondition ) ; if ( bottom == l.end() ) { // Non trouvé, que faire (une exception, peut-être) } Iter top = std::find_if( l.rbegin(), List::reverse_iterator( bottom ), topCondition ).base() ; if ( top == bottom ) { // Non truové... } if ( ! conditionsInclusives && top != bottom ) { -- top ; // se positionne sur le dernier élément if ( top != bottom ) { ++ bottom ; // et au delà du premier élément, } // pour ne pas les effacer. } l.erase( bottom, top ) ;
Reste la question de ce que tu veux faire si les récherches échouent. (Le code ici n'efface rien dans ce cas-là. Encore que c'est à vérifier -- je ne me suis pas penché trop sur les conditions limites.)
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34