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

etudiant--> help

22 réponses
Avatar
elekis
bonjour, voila, dans un bete progrmme dont j'essaie de tester les
classes, je cle avec la fonction delete
ce prog creer une bete liste, affice les valeurs, detruit le denier
element, pis raffiche mais je sais pas pourquoi il ne veux pas me
supprimer le dernier element

#include <iostream>
using namespace std;

class elem
{
public:
elem* next;
int info;
elem(int);
};
elem::elem(int a)
{
info = a;
next = NULL;
}
main()
{
elem* tete= new elem(2);//element bidon
elem * p=tete;
for (int i= 1026; i<1093; i = i+12)
{
p->next = new elem(i);
p=p->next;
}
for(p = tete->next;p!=NULL;p=p->next)
cout<<p->info<<" ";
cout <<endl;

for(p = tete;p->next!=NULL;p=p->next)
;//atteint le dernier element

//est sencé le supprimer, mais sais pas pouruqoi, il ne veux pas.
delete p;

cout <<p->info<<endl;

for(p = tete->next;p!=NULL;p=p->next)
cout<<p->info<<" ";
cout << endl;

}


1026 1038 1050 1062 1074 1086
1086
1026 1038 1050 1062 1074 1086


j'ai deja chercher dans deux trois boucains, ainsi que donas mon cours,
mais je trouve pas

merci

a++

10 réponses

1 2 3
Avatar
Anthony Fleury
elekis wrote:

bonjour, voila, dans un bete progrmme dont j'essaie de tester les
classes, je cle avec la fonction delete
ce prog creer une bete liste, affice les valeurs, detruit le denier
element, pis raffiche mais je sais pas pourquoi il ne veux pas me
supprimer le dernier element

main()
int main() plutot


//est sencé le supprimer, mais sais pas pouruqoi, il ne veux pas.
delete p;


Et le "supprime"...


cout <<p->info<<endl;

for(p = tete->next;p!=NULL;p=p->next)
cout<<p->info<<" ";
cout << endl;

}


Le comportement que obtenu est des plus normal.
Tu es d'accord que ta dernière boucle va se faire jusqu'à ce qu'elle
rencontre un pointeur NULL, c'est à dire que ta chaine soit arrivé à la
fin. Or, ce NULL n'est rencontré qu'après affichage de ton dernier élement
que tu viens de supprimer. Par chance, tu as fait un delete et l'affichage
juste après donc la mémoire n'a pas bougé, mais en clair là tu lis dans une
zone mémoire qui ne t'appartient plus. En clair, dans ce cas c'est comme si
ta liste chainée n'avait pas d'élement final et donc tu vas lire en mémoire
jusqu'à un avoir de la chance comme ici ou te prendre un SIGSEGV.

lorsque tu supprimes ton pointeur p, il te faut donc replacer la fin de ta
liste. En clair, ton avant dernier élement ne doit plus pointer sur le
dernier qui sera supprimé mais sur NULL.

pour que ce soit plus facile à faire, faut lire ta liste avec un coup
d'avance, pour te trouver sur le bon pointeur (l'avant dernier) et
supprimer le suivant d'où tu te trouves :

p = tete;

if(!p) {
// pas de liste...
}

else if(!p->next) { // un seul élement
delete p;
p = NULL;
}

else {
for(p = tete;p->next->next !=NULL ;p=p->next);
// atteint l'avant dernier élement...
delete p->next;
p->next = NULL;
}

Anthony
--
"I should have seen it would be this way
I should have known from the start what she's up to
When you have loved and you've lost someone
You know what it feels like to lose" -- The Rasmus

Avatar
M. B.
D'abord 'delete' n'est pas une fonction mais un
operateur du langage.

Ca n'efface pas la memoire, ca la libere. Apres un 'delete',
elle est concideree comme libre par le systeme d'exploitation
pour une allocation ulterieure.

Ton dernier element me semble bien desalloue (et pas effacer !).

Comme tu lis juste derriere le contenu de la memoire liberee, son
contenu n'a pas change et tu continues a lire la valeur de l'element
supprime.

Plus grave : ton avant-dernier element pointe a present vers un element
qui n'existe plus, meme si au moment ou tu lis, les valeurs sont
toujours en memoire.

Lorsque tu detruis un element de la liste, il faut mettre a 'NULL'
le champ 'next' de l'element précédent.

MB

"elekis" a écrit dans le message de news:
4049d827$0$324$
bonjour, voila, dans un bete progrmme dont j'essaie de tester les
classes, je cle avec la fonction delete
ce prog creer une bete liste, affice les valeurs, detruit le denier
element, pis raffiche mais je sais pas pourquoi il ne veux pas me
supprimer le dernier element

#include <iostream>
using namespace std;

class elem
{
public:
elem* next;
int info;
elem(int);
};
elem::elem(int a)
{
info = a;
next = NULL;
}
main()
{
elem* tete= new elem(2);//element bidon
elem * p=tete;
for (int i= 1026; i<1093; i = i+12)
{
p->next = new elem(i);
p=p->next;
}
for(p = tete->next;p!=NULL;p=p->next)
cout<<p->info<<" ";
cout <<endl;

for(p = tete;p->next!=NULL;p=p->next)
;//atteint le dernier element

//est sencé le supprimer, mais sais pas pouruqoi, il ne veux pas.
delete p;

cout <<p->info<<endl;

for(p = tete->next;p!=NULL;p=p->next)
cout<<p->info<<" ";
cout << endl;

}


1026 1038 1050 1062 1074 1086
1086
1026 1038 1050 1062 1074 1086


j'ai deja chercher dans deux trois boucains, ainsi que donas mon cours,
mais je trouve pas

merci

a++


Avatar
Manuel
bonjour, voila, dans un bete progrmme dont j'essaie de tester les
classes, je cle avec la fonction delete
ce prog creer une bete liste, affice les valeurs, detruit le denier
element, pis raffiche mais je sais pas pourquoi il ne veux pas me
supprimer le dernier element

#include <iostream>
using namespace std;

class elem
{
public:


"private: " serait bien mieux ici

elem* next;
int info;
public:

elem(int);
};


C'est mieux d'encapsuler les données en général.

elem::elem(int a)
{
info = a;
next = NULL;
}
main()


int main() // on le dira jamais assez ;-)

{
elem* tete= new elem(2);//element bidon
elem * p=tete;
for (int i= 1026; i<1093; i = i+12)
{
p->next = new elem(i);
p=p->next;
}
for(p = tete->next;p!=NULL;p=p->next)
cout<<p->info<<" ";
cout <<endl;

for(p = tete;p->next!=NULL;p=p->next)
;//atteint le dernier element

//est sencé le supprimer, mais sais pas pouruqoi, il ne veux pas.
delete p;

cout <<p->info<<endl;



Il est bel et bien supprimé et tenter d'accéder à sa mémoire
est une erreur (undefined behavior). De plus, le pointeur
"next" de l'élément précédent pointe sur cette mémoire.
Cette classe est encore incomplète... et dangereuse.
Pourquoi ne pas utiliser std::list<> ?

for(p = tete->next;p!=NULL;p=p->next)
cout<<p->info<<" ";
cout << endl;

}


1026 1038 1050 1062 1074 1086
1086
1026 1038 1050 1062 1074 1086



Il semble que la liste ne soit pas modifiée mais c'est une illusion.


j'ai deja chercher dans deux trois boucains, ainsi que donas mon cours,
mais je trouve pas

merci

a++



--

- Manuel
to reply, swap the name with the domain.

Avatar
farid bouzemarene
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Manuel wrote:
|
|>bonjour, voila, dans un bete progrmme dont j'essaie de tester les
|>classes, je cle avec la fonction delete
|>ce prog creer une bete liste, affice les valeurs, detruit le denier
|>element, pis raffiche mais je sais pas pourquoi il ne veux pas me
|>supprimer le dernier element
|>
|>#include <iostream>
|>using namespace std;
|>
|>class elem
|>{
|>public:
|
|
| "private: " serait bien mieux ici
|
|
|>elem* next;
|>int info;
|
| public:
|
|>elem(int);
|>};
|
|
| C'est mieux d'encapsuler les données en général.
|
|
|>elem::elem(int a)
|>{
|>info = a;
|>next = NULL;
|>}
|>main()
|
|
| int main() // on le dira jamais assez ;-)
|
|
|>{
|>elem* tete= new elem(2);//element bidon
|>elem * p=tete;
|>for (int i= 1026; i<1093; i = i+12)
|>{
|>p->next = new elem(i);
|>p=p->next;
|>}
|>for(p = tete->next;p!=NULL;p=p->next)
|>cout<<p->info<<" ";
|>cout <<endl;
|>
|>for(p = tete;p->next!=NULL;p=p->next)
|>;//atteint le dernier element
|>
|>//est sencé le supprimer, mais sais pas pouruqoi, il ne veux pas.
|>delete p;
|>
|>cout <<p->info<<endl;
|>
|
|
| Il est bel et bien supprimé et tenter d'accéder à sa mémoire
| est une erreur (undefined behavior). De plus, le pointeur
| "next" de l'élément précédent pointe sur cette mémoire.
| Cette classe est encore incomplète... et dangereuse.
| Pourquoi ne pas utiliser std::list<> ?
|
|
|>for(p = tete->next;p!=NULL;p=p->next)
|>cout<<p->info<<" ";
|>cout << endl;
|>
|>}
|>
|>
|>1026 1038 1050 1062 1074 1086
|>1086
|>1026 1038 1050 1062 1074 1086
|>
|
|
| Il semble que la liste ne soit pas modifiée mais c'est une illusion.
|
|
|>j'ai deja chercher dans deux trois boucains, ainsi que donas mon cours,
|>mais je trouve pas
|>
|>merci
|>
|>a++
|
|
|
pourquoi int main()???

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iQCVAwUBQEoxfdlroYU295zBAQIqEwP/ZoMGfbOl1wMqlSleY0aO9JaEG/trAbxt
StFfLM12T0IKHEXGQ8osYMMWrFrb3Durw/7tSVY2m52Xiyoq56Lav+wSz286hTlR
BT+C8gDUr/72ZimJDBMnpTy8/y9jZuHYKXJq087pSr5Ml26ITka8At+0ogd8yQdr
foevKyRaIBI =iCpS
-----END PGP SIGNATURE-----
Avatar
Anthony Fleury
farid bouzemarene wrote:


pourquoi int main()???


Euh c'était peut etre pas la peine de citer tout le message pour rajouter
une ligne ? :)

Enfin bref, pourquoi int main() ? Peut-être parce que c'est la version
conseillée par la norme ? En effet il y a deux versions de main
acceptables :

int main()
et
int main(int argc, char** argv) ou équivalent pour le char** (notamment
char* []).

Ce qui fait que main recoit les arguments de la ligne de commande ou les
ignore, et renvoie une valeur au système d'exploitation disant comment
l'execution du programme s'est déroulée (cette valeur est utilisée
notamment dans les systèmes unix où le shell permet d'enchainer les
commandes avec des et, des ou ou autre selon la valeur renvoyée par le
programme).

De plus, si aucune valeur n'est spécifiée en retour de main, le système
recoit EXIT_SUCCESS.

Pour précision aussi, la déclaration
main()
contenait de toute facon une erreur. Si la personne ne veut renvoyer aucune
valeure dans main, il faut écrire void main() car le type de retour doit
obligatoirement être précisé pour une fonction, dans le cas ou on ne
retourne rien c'est void, et il n'y a pas de type int implicite en C++
comme il y a pu y avoir en C, ou cette définition était équivalente à int
main().

Anthony
--
"I should have seen it would be this way
I should have known from the start what she's up to
When you have loved and you've lost someone
You know what it feels like to lose" -- The Rasmus

Avatar
Manuel
[...]
Pour précision aussi, la déclaration
main()
contenait de toute facon une erreur. Si la personne ne veut renvoyer
aucune

valeure dans main, il faut écrire void main() car le type de retour doit



int main()
{
// bla bla et puis plus rien, pas de return à la fin.
}

En C++ le compilateur "ajoute" implicitement
return 0;

Mais c'est pas une bonne habitude à prendre, AMHA... ;-)

--

- Manuel
to reply, swap the name with the domain.

Avatar
Anthony Fleury
Manuel wrote:

[...]
Pour précision aussi, la déclaration
main()
contenait de toute facon une erreur. Si la personne ne veut renvoyer
aucune

valeure dans main, il faut écrire void main() car le type de retour doit



int main()
{
// bla bla et puis plus rien, pas de return à la fin.
}

En C++ le compilateur "ajoute" implicitement
return 0;

Mais c'est pas une bonne habitude à prendre, AMHA... ;-)



Hum je me suis mal exprimé surement, je voulais dire qu'une fonction en C++
doit avoir un type de retour quitte à ce que ce soit void.
En clair, f() { } n'est pas valide, il faut écrire void f() { }
Je voulais notifier que la notation main() n'a aucun sens en C++ standard,
une fonction devant avoir un type de retour, [alors que cette notation est
valide en C90]

Au passage, le return 0; est vraiment une habitude à prendre car certains
compilateurs assez anciens n'ajoutent pas ce return 0; mais transforment le
type de main en void si aucune valeur de retour n'est spécifiée (c'est le
cas de visual C++ 5 qui je l'accorde est sorti avant la norme, donc c'est
normal).

Anthony
--
"I should have seen it would be this way
I should have known from the start what she's up to
When you have loved and you've lost someone
You know what it feels like to lose" -- The Rasmus


Avatar
farid bouzemarene
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

ok ,
moi j'utilisais toujours main() sans type de retour et ça a toujours
marché....

mais bon je viens de comprendre que c'est normal en c90
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iQCVAwUBQEpgp9lroYU295zBAQKDAgP9ExPUzdgb/BqDFkW1u0bQK2zzw32a1iRV
Xs/WX5Ee+Y7sf7ok1b/QbC0K9gQuc09TDjFk19GCfUBSmkV4uw+wAMOpiXgHzlq2
nkvHD/f2VyziuTiQ8qb+2UYxZ3mti28zHaYDYddSQPyuJ3KqnHZS965wiFN60+zb
HCb2N/nWxhE ÔOQ
-----END PGP SIGNATURE-----
Avatar
Manuel

[...]
valeure dans main, il faut écrire void main() car le type de retour
doit





int main()
{
// bla bla et puis plus rien, pas de return à la fin.
}

En C++ le compilateur "ajoute" implicitement
return 0;

Mais c'est pas une bonne habitude à prendre, AMHA... ;-)



Hum je me suis mal exprimé surement, je voulais dire qu'une fonction en
C++

doit avoir un type de retour quitte à ce que ce soit void.
En clair, f() { } n'est pas valide, il faut écrire void f() { }


Absolument d'accord.

Je voulais notifier que la notation main() n'a aucun sens en C++ standard,
une fonction devant avoir un type de retour, [alors que cette notation est
valide en C90]


...et je voulais juste souligner qu'un type de retour autre que "int" pour
la fonction "main" n'a aucun sens non plus en C++ standard.
Sinon, je suis d'accord avec ce que tu dis.

Au passage, le return 0; est vraiment une habitude à prendre car certains


Toujours d'accord... je disais que c'est une mauvaise habitude de *ne pas*
retourner une valeur dans "main" et je trouve dommage que ce soit
facultatif.
J'aurais préféré que ce soit une erreur ou au pire un warning.

--

- Manuel
to reply, swap the name with the domain.



Avatar
Gabriel Dos Reis
Anthony Fleury writes:

| Au passage, le return 0; est vraiment une habitude à prendre car certains
| compilateurs assez anciens n'ajoutent pas ce return 0;

Je veux des noms.

Ce comportement a toujours fait partie de C++ depuis des lustres.

| mais transforment le
| type de main en void si aucune valeur de retour n'est spécifiée (c'est le
| cas de visual C++ 5

Si Visual C++-5 decide que c'est que comprend son environnement
d'éxécution, alors aourter return 0 ne change rien.

| qui je l'accorde est sorti avant la norme, donc c'est
| normal).

???

-- Gaby
1 2 3