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
Patrick Mézard
Comment je peux supprimer un element sur deux(par exemple les elements d'indices impair) dans une list? J'ai essaye des choses comme cela :
1- list<double> X; list<double>::iterator iter; for (int k=0; k<X.size() ; k++) { ++iter; if (!(k%2)) { X.pop_back(); }
}
pop_back() enlève le dernier élément du conteneur, indépendamment de tout itérateur. Cela ne peut donc pas marcher.
2- mais je veux avoir une syntaxe de ce type:
for (iter=X.begin(); iter!=X.begin() ; iter++) {
if (!(k%2)) { X.erase(iter); }
}
mais il marche pas!! j'ai l'impression que l'iterateur est aussi ecrase parce que l'excution s'interompe des le deuxieme tour de boucle
Exactement (et ton test de fin de boucle n'est pas bon). erase(p) détruit l'objet pointé par p invalide l'itérateur "p" et parfois quelques autres suivant le type du conteneur. Dans le cas d'une std::list, seul "p" est invalidé. Ton problème est que tu voudrais continuer à itérer. On peut incrémenter "iter" en postfixe, histoire de le modifier tout en récupérant la valeur précédente :
Suivant l'implémentation de la STL dont tu disposes tu peux aussi récupérer la valeur de retour du erase() :
for(iter=X.begin(); iter!=X.end(); ++iter) { iter = X.erase(iter); if(iter==X.end()) break; }
Tu devrais t'intéresser à la notion de validité d'itérateur dans la STL, tu risques de perdre beaucoup de temps autrement.
-- Patrick Mézard
Comment je peux supprimer un element sur deux(par exemple les elements
d'indices impair) dans une list?
J'ai essaye des choses comme cela :
1-
list<double> X;
list<double>::iterator iter;
for (int k=0; k<X.size() ; k++)
{
++iter;
if (!(k%2)) { X.pop_back(); }
}
pop_back() enlève le dernier élément du conteneur, indépendamment de
tout itérateur. Cela ne peut donc pas marcher.
2- mais je veux avoir une syntaxe de ce type:
for (iter=X.begin(); iter!=X.begin() ; iter++)
{
if (!(k%2)) { X.erase(iter); }
}
mais il marche pas!! j'ai l'impression que l'iterateur est aussi ecrase
parce que l'excution s'interompe des le deuxieme tour de boucle
Exactement (et ton test de fin de boucle n'est pas bon).
erase(p) détruit l'objet pointé par p invalide l'itérateur "p" et
parfois quelques autres suivant le type du conteneur. Dans le cas d'une
std::list, seul "p" est invalidé. Ton problème est que tu voudrais
continuer à itérer. On peut incrémenter "iter" en postfixe, histoire de
le modifier tout en récupérant la valeur précédente :
Comment je peux supprimer un element sur deux(par exemple les elements d'indices impair) dans une list? J'ai essaye des choses comme cela :
1- list<double> X; list<double>::iterator iter; for (int k=0; k<X.size() ; k++) { ++iter; if (!(k%2)) { X.pop_back(); }
}
pop_back() enlève le dernier élément du conteneur, indépendamment de tout itérateur. Cela ne peut donc pas marcher.
2- mais je veux avoir une syntaxe de ce type:
for (iter=X.begin(); iter!=X.begin() ; iter++) {
if (!(k%2)) { X.erase(iter); }
}
mais il marche pas!! j'ai l'impression que l'iterateur est aussi ecrase parce que l'excution s'interompe des le deuxieme tour de boucle
Exactement (et ton test de fin de boucle n'est pas bon). erase(p) détruit l'objet pointé par p invalide l'itérateur "p" et parfois quelques autres suivant le type du conteneur. Dans le cas d'une std::list, seul "p" est invalidé. Ton problème est que tu voudrais continuer à itérer. On peut incrémenter "iter" en postfixe, histoire de le modifier tout en récupérant la valeur précédente :
Par curiosité : pourquoi le test avec break ? Il me semble qu'il faut double emploi avec la condition dans le for.
Suivant l'implémentation de la STL dont tu disposes tu peux aussi récupérer la valeur de retour du erase() :
for(iter=X.begin(); iter!=X.end(); ++iter) { iter = X.erase(iter); if(iter==X.end()) break; }
Comment ça, suivant l'implémentation ? La fonction erase renvoie toujours un itérateur sur l'élément qui suivait l'élément éffacé.
Pour son problème précis :
list<double>::iterator iter = X.begin() ; while ( iter != X.end() ) { if ( k % 2 == 0 ) { iter = X.erase( iter ) ; // ou : X.erase( iter ++ ) ; } else { ++ iter ; } }
Tu devrais t'intéresser à la notion de validité d'itérateur dans la STL, tu risques de perdre beaucoup de temps autrement.
Je dirais que le fait qu'il faut s'y intéresser autant fait déjà perdre beaucoup de temps. Dans les collections pré-norme, j'éstîmais que le support pour quelque chose comme :
for ( Iterator iter( collection ) ; ! iter.isDone() ; iter.next() ) { if ( condition( iter.current() ) ) { collection.remove( iter ) ; } }
était un minimum d'une collection bien conçue. (À vrai dire, je le crois encore. Avec le corollaire que j'estîme la STL assez mal conçue.)
-- 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
Par curiosité : pourquoi le test avec break ? Il me semble qu'il
faut double emploi avec la condition dans le for.
Suivant l'implémentation de la STL dont tu disposes tu peux
aussi récupérer la valeur de retour du erase() :
for(iter=X.begin(); iter!=X.end(); ++iter)
{
iter = X.erase(iter);
if(iter==X.end())
break;
}
Comment ça, suivant l'implémentation ? La fonction erase renvoie
toujours un itérateur sur l'élément qui suivait l'élément
éffacé.
Pour son problème précis :
list<double>::iterator iter = X.begin() ;
while ( iter != X.end() ) {
if ( k % 2 == 0 ) {
iter = X.erase( iter ) ;
// ou : X.erase( iter ++ ) ;
} else {
++ iter ;
}
}
Tu devrais t'intéresser à la notion de validité d'itérateur
dans la STL, tu risques de perdre beaucoup de temps autrement.
Je dirais que le fait qu'il faut s'y intéresser autant fait déjà
perdre beaucoup de temps. Dans les collections pré-norme,
j'éstîmais que le support pour quelque chose comme :
for ( Iterator iter( collection ) ;
! iter.isDone() ;
iter.next() ) {
if ( condition( iter.current() ) ) {
collection.remove( iter ) ;
}
}
était un minimum d'une collection bien conçue. (À vrai dire, je
le crois encore. Avec le corollaire que j'estîme la STL assez
mal conçue.)
--
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
Par curiosité : pourquoi le test avec break ? Il me semble qu'il faut double emploi avec la condition dans le for.
Suivant l'implémentation de la STL dont tu disposes tu peux aussi récupérer la valeur de retour du erase() :
for(iter=X.begin(); iter!=X.end(); ++iter) { iter = X.erase(iter); if(iter==X.end()) break; }
Comment ça, suivant l'implémentation ? La fonction erase renvoie toujours un itérateur sur l'élément qui suivait l'élément éffacé.
Pour son problème précis :
list<double>::iterator iter = X.begin() ; while ( iter != X.end() ) { if ( k % 2 == 0 ) { iter = X.erase( iter ) ; // ou : X.erase( iter ++ ) ; } else { ++ iter ; } }
Tu devrais t'intéresser à la notion de validité d'itérateur dans la STL, tu risques de perdre beaucoup de temps autrement.
Je dirais que le fait qu'il faut s'y intéresser autant fait déjà perdre beaucoup de temps. Dans les collections pré-norme, j'éstîmais que le support pour quelque chose comme :
for ( Iterator iter( collection ) ; ! iter.isDone() ; iter.next() ) { if ( condition( iter.current() ) ) { collection.remove( iter ) ; } }
était un minimum d'une collection bien conçue. (À vrai dire, je le crois encore. Avec le corollaire que j'estîme la STL assez mal conçue.)
-- 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
Fabien LE LEZ
On 27 Dec 2005 01:59:29 -0800, "kanze" :
Comment ça, suivant l'implémentation ? La fonction erase renvoie toujours un itérateur sur l'élément qui suivait l'élément éffacé.
Disons qu'il faut vérifier que l'implémentation utilisée est conforme. Je connais une SL qui contient std::basic_string<> mais "void std::list<>::erase()".
On 27 Dec 2005 01:59:29 -0800, "kanze" <kanze@gabi-soft.fr>:
Comment ça, suivant l'implémentation ? La fonction erase renvoie
toujours un itérateur sur l'élément qui suivait l'élément
éffacé.
Disons qu'il faut vérifier que l'implémentation utilisée est conforme.
Je connais une SL qui contient std::basic_string<> mais
"void std::list<>::erase()".
Comment ça, suivant l'implémentation ? La fonction erase renvoie toujours un itérateur sur l'élément qui suivait l'élément éffacé.
Disons qu'il faut vérifier que l'implémentation utilisée est conforme. Je connais une SL qui contient std::basic_string<> mais "void std::list<>::erase()".
Par curiosité : pourquoi le test avec break ? Il me semble qu'il faut double emploi avec la condition dans le for.
Parce qu'il me semble que (iter!=X.end()) est une précondition à l'incrémentation de iter.
En effet. J'avais raté le fait que tu incrémentes deux fois à chaque passage. (Je ne pensais pas tellement au cas précis de supprimer un élément sur deux, mais au cas plus général de supprimer un élément dans une boucle.)
-- 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
Par curiosité : pourquoi le test avec break ? Il me semble
qu'il faut double emploi avec la condition dans le for.
Parce qu'il me semble que (iter!=X.end()) est une précondition
à l'incrémentation de iter.
En effet. J'avais raté le fait que tu incrémentes deux fois à
chaque passage. (Je ne pensais pas tellement au cas précis de
supprimer un élément sur deux, mais au cas plus général de
supprimer un élément dans une boucle.)
--
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
Par curiosité : pourquoi le test avec break ? Il me semble qu'il faut double emploi avec la condition dans le for.
Parce qu'il me semble que (iter!=X.end()) est une précondition à l'incrémentation de iter.
En effet. J'avais raté le fait que tu incrémentes deux fois à chaque passage. (Je ne pensais pas tellement au cas précis de supprimer un élément sur deux, mais au cas plus général de supprimer un élément dans une boucle.)
-- 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