Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

STL et list

20 réponses
Avatar
gg
Bonjour,

J'essaie tant bien que mal d'utiliser la librarie STL, et particulièrement
la classe "list".
Ma question est donc la suivante, ai-je le droit de faire ça, sans que mon
programme plante ?

Voici un listing "simplifié":

dans un liste : list<char *> test; je met divers mots avec
test.push_front();
Ensuite je parcous cette liste.

list<char *>::iterator i;

for (i=test.begin(); i!=test.end(); i++)
{
if (strcmp(*i,"effacer")==0)
test.erase(i);
}
Le programme plante. Je me doute bien qu'il y a problème d'index. Mais même
si je fais le test:

if (test.erase(i)==test.end()) return;

C'est mieux , mais pas encore ça.

Si vous avez une idée, je suis preneur.
Merci,

gg

10 réponses

1 2
Avatar
Christophe Bondoin
Je dirais (sans avoir vérifié) qu'il faut ecrire :

if (strcmp(*i,"effacer")==0)
i = test.erase(i);

car la fonction erase renvoie un itérateur. si on fait erase(i), i n'est
plus valide et le i++ plante. je pense que l'itérateur renvoyé par erase
est quand à lui valide (et s'il est égal à end, on s'arrête 'normalement').
Avatar
loufoque

for (i=test.begin(); i!=test.end(); i++)
{
if (strcmp(*i,"effacer")==0)
test.erase(i);
}
Le programme plante.


Normal.
Il faut faire

for(i=test.begin(); i!=test.end(); )
{
if(strcmp(*i, "effacer") == 0)
test.erase(i);
else
++i;
}

Et tu ferais mieux d'utiliser std::string.

Avatar
Cyrille

Normal.
Il faut faire

for(i=test.begin(); i!=test.end(); )
{
if(strcmp(*i, "effacer") == 0)
test.erase(i);
else
++i;
}


Plus exactement:
for(i=test.begin(); i!=test.end(); )
{
if(strcmp(*i, "effacer") == 0)
i = test.erase(i);
else
++i;
}

--
Les lois sont toujours utiles à ceux qui possèdent et nuisibles à ceux
qui n'ont rien. ~ Rousseau, du Contrat Social.

Avatar
Fabien LE LEZ
On Tue, 10 Oct 2006 22:54:40 +0200, "gg" :

list<char *> test; je met divers mots avec
test.push_front();


Tu cherches les emmerdes. Utilise plutôt list<string>.

Avatar
kanze
Cyrille wrote:

Normal.
Il faut faire

for(i=test.begin(); i!=test.end(); )
{
if(strcmp(*i, "effacer") == 0)
test.erase(i);
else
++i;
}


Plus exactement:
for(i=test.begin(); i!=test.end(); )
{
if(strcmp(*i, "effacer") == 0)
i = test.erase(i);
else
++i;
}


Tout à fait. Une autre stratégie, surtout utile si le contenu
de la boucle est complexe, c'est :

list< char* >::iterator i = test.begin() ;
while ( i != test.end() ) {
std::list< char* >::iterator next = i ;
++ next ;
// On fait ce qu'on veut ici...
i = next ;
}

--
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


Avatar
gg
"gg" a écrit dans le message de news:
452c0891$0$25908$

Bonjour,

J'essaie tant bien que mal d'utiliser la librarie STL, et particulièrement
la classe "list".
Ma question est donc la suivante, ai-je le droit de faire ça, sans que mon
programme plante ?

Voici un listing "simplifié":

dans un liste : list<char *> test; je met divers mots avec
test.push_front();
Ensuite je parcous cette liste.

list<char *>::iterator i;

for (i=test.begin(); i!=test.end(); i++)
{
if (strcmp(*i,"effacer")==0)
test.erase(i);
}
Le programme plante. Je me doute bien qu'il y a problème d'index. Mais
même si je fais le test:

if (test.erase(i)==test.end()) return;

C'est mieux , mais pas encore ça.

Si vous avez une idée, je suis preneur.
Merci,

gg



Merci à tous pour vos réponses très claires.

Ceci m'amène à un autre problème que je trouve plutôt délicat. Comment
inverser deux éléments connus d'une liste en un minimum de temps ?
Exemple, j'ai une liste (de pointeurs pour être exact), et je désirerai
inverser deux éléments de cette liste (et ne pas inverser le contenu des
pointeurs), d'autre part, dans le programme, d'autres variables utilisent
ces éléments.

Encore une fois, merci d'avance de votre réponse

gg

Avatar
Arnaud Debaene
"gg" a écrit dans le message de news:
452cd988$0$27395$

Ceci m'amène à un autre problème que je trouve plutôt délicat. Comment
inverser deux éléments connus d'une liste en un minimum de temps ?
Exemple, j'ai une liste (de pointeurs pour être exact), et je désirerai
inverser deux éléments de cette liste (et ne pas inverser le contenu des
pointeurs), d'autre part, dans le programme, d'autres variables utilisent
ces éléments.


std::list<MonType*>::iterator pos1= ///.....
std::list<MonType*>::iterator pos2= ///.....
std::swap(*pos1, *pos2);

Arnaud

Avatar
Stephane Wirtel
gg wrote:
Bonjour,

J'essaie tant bien que mal d'utiliser la librarie STL, et particulièrement
la classe "list".
Ma question est donc la suivante, ai-je le droit de faire ça, sans que mon
programme plante ?

Voici un listing "simplifié":

dans un liste : list<char *> test; je met divers mots avec
test.push_front();
Ensuite je parcous cette liste.

list<char *>::iterator i;
très mauvaise idée


for (i=test.begin(); i!=test.end(); i++)
attention, ton code recalcule toujours la fin de ta collection,

autant écrire ceci.

std::list< char * >::iterator it = test.begin(), itEnd = test.end();
for( it != itEnd; ++it ) {
}

de plus, je vois que tu réalises une postincrémentation sur ton
iterateur, ce qui n'est pas forcément judicieux.
autant réaliser une préincrémentation sinon, ça économisera des ressources.
{
if (strcmp(*i,"effacer")==0)
test.erase(i);
}
Le programme plante. Je me doute bien qu'il y a problème d'index. Mais même
si je fais le test:

if (test.erase(i)==test.end()) return;

C'est mieux , mais pas encore ça.

Si vous avez une idée, je suis preneur.
Merci,

gg
malgré toutes les réponses, je te propose tout de même quelque chose de

propre.

typedef std::vector< std::string > StringList;

StringList strList;
/// ajoute tes éléments ici

strList.erase( std::remove( strList.begin(), strList.end(), "effacer" ),
strList.end() );

et normalement tout est correctement éffacer.

qu'en penses-tu ?

Stef

Avatar
kanze
Arnaud Debaene wrote:
"gg" a écrit dans le message de news:
452cd988$0$27395$

Ceci m'amène à un autre problème que je trouve plutôt
délicat. Comment inverser deux éléments connus d'une liste
en un minimum de temps ? Exemple, j'ai une liste (de
pointeurs pour être exact), et je désirerai inverser deux
éléments de cette liste (et ne pas inverser le contenu des
pointeurs), d'autre part, dans le programme, d'autres
variables utilisent ces éléments.


std::list<MonType*>::iterator pos1= ///.....
std::list<MonType*>::iterator pos2= ///.....
std::swap(*pos1, *pos2);


Ça marche si ce qu'il a voulu dire, c'est de ne pas invalider
des pointeurs à des objets dont les pointeurs se trouvent dans
la liste. Sa mention de pointeurs rend la question un peu vague,
mais si on a des pointeurs à des éléments de la liste (quelque
soit le type d'élément -- des pointeurs à des pointeurs, donc,
si la liste contient des pointeurs), et qu'on veut qu'ils
pointent toujours au même objet, il faut faire quelque chose du
genre :

//! pre
//! pos1 et pos2 sont des itérateurs dans l.
//! pos1 != pos2.
// ---------------------------------------------------------------
template< typename T >
void
lswap(
std::list< T >& l,
typename std::list< T >::iterator
pos1,
typename std::list< T >::iterator
pos2 )
{
std::list< T > a ;
a.splice( a.begin(), l, pos1 ++ ) ;
std::list< T > b ;
b.splice( b.begin(), l, pos2 ++ ) ;
l.splice( pos1, b ) ;
l.splice( pos2, a ) ;
}

À la suite, les éléments à pos1 et à pos2 sont échangés, et t out
itérateur, pointeur ou référence qui désignait l'élément à po s1
le désigne encore, à sa nouvelle position, de même pour pos2.
(En fait, je suis sûr qu'on pourrait le faire avec une seule
liste temporaire, voire aucune :

l.splice( pos2, l, pos1 ++ ) ;
l.splice( pos1, l, pos2 ) ;

mais je me sens pas sûr en ce qui concerne les cas limites, par
exemple quand pos1 et pos2 sont adjacents, et je trouve la
version avec deux temporaires bien plus simple à comprendre.)

--
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


Avatar
Alain Gaillard

très mauvaise idée


for (i=test.begin(); i!=test.end(); i++)


attention, ton code recalcule toujours la fin de ta collection,
autant écrire ceci.

std::list< char * >::iterator it = test.begin(), itEnd = test.end();
for( it != itEnd; ++it ) {
}

de plus, je vois que tu réalises une postincrémentation sur ton
iterateur, ce qui n'est pas forcément judicieux.
autant réaliser une préincrémentation sinon, ça économisera des ressources.


Voilà de quoi relancer un débat à peine clos, n'est-ce pas James ;)

--
Alain


1 2