FONCTION QUI SUPPRIME UN CARACTÈRE DONNÉ DANS UNE CHAINE EN UTILISANT LES POINTE
Utilisateur anonyme
-
7 févr. 2006 à 23:36
cs_Forman
Messages postés600Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 6 avril 2010
-
28 mai 2006 à 17:23
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
cs_Forman
Messages postés600Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 6 avril 20101 28 mai 2006 à 17:23
Je n'étais pas encore venu foutre ma m**** lol
En mettant le caractère #0 au milieu d'une chaîne, fOxi, tu ne changes pas sa longueur. Exemple:
const s=#1#2#0#3#4;
Avec cet exemple de chaîne qui fait 5 caractères, le compilateur te dira que Length(s)=5 (la convention qu'un chaîne se termine au premier caractère #0 est vraie - et en partie seulement - pour le C mais pas en Delphi). De plus, même en C le fait qu'un char* contienne un \0 à un endroit ne signifie pas qu'il n'y a pas encore des données après, c'est juste une convention commode qu'utilisent ceux qui écrivent les API pour s'y retrouver.
Pour Delphi, une chaîne de type string est implémentée par une sorte d'interface sous-jacente (pour le ref-counting) avec un champ Length. C'est aussi le cas des tableaux dynamiques. C'est par exemple pour ça que si tu as:
var s:string;
@s ne pointe pas vers le premier caractère de la chaîne, mais vers cette fameuse interface de gestion des chaînes (idem pour les tableaux dynamiques). Tu peux calculer la taille en mémoire occupée par ce que Borland rajoutte (en plus des caractères) à une chaîne en calculant:
Integer(@s[1])-Integer(@s)
Je crois (mais ça demanderait à être revérifié) que ça fait 8 octets (tout simplement un entier integer contenant la longueur de la chaîne + un autre contenant le nombre de références à celle-ci).
Une version encore plus compacte de la fonction de Fred serait:
function SuppChar(const S : string; const C : char) : string;
var pS, pR : PChar; l : Integer;
begin
l := length(S)
SetLength(Result, l);
pS := PChar(S);
pR := PChar(Result);
While pS^ <> #0 do begin
if pS[0] <> C then begin
pR[0] := pS[0];
Inc(pR);
end else
Dec(l);
Inc(pS);
end;
SetLength(Result, l);
end;
Je ne pense pas que le Dec(l) soit trop gourmand en resources ^^
Dernière remarque, tu peux t'affranchir de faire Result:='' au début de la fonction car Delphi par défaut le fait pour toi (comme il le fait pour toutes les variables qui contiennent des interfaces "ref-counted").
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 16 avril 2006 à 15:57
en effet fred ...
alors tout simplement le rajout de :
function SuppChar(const S : string; const C : char) : string;
var pS, pR : PChar;
begin
Result := '';
SetLength(Result, length(S));
pS := PChar(S);
pR := PChar(Result);
While pS^ <> #0 do begin
if pS[0] <> C then begin
pR[0] := pS[0];
Inc(pR);
end;
Inc(pS);
end;
pR[0] := #0;
end;
et hop la chaine est finie...
Fred_Ca_Pulse
Messages postés20Date d'inscriptionmercredi 15 mars 2006StatutMembreDernière intervention19 juin 2008 15 mars 2006 à 11:02
Mais non, c'est seulement une blague, bien sûr qu'elle n'existe pas depuis 50 ans ... j'étais même pas né à l'époque ... et le Pascal non plus effectivement :)
C'était juste pour faire un peu d'ironie sur le temps passé à écrire ou à utiliser du code, et la possibilité qu'on puisse toujours avoir des bugs dedans ou qu'il existe une meilleure façon de l'écrire.
FRED
jlen100
Messages postés1606Date d'inscriptionsamedi 10 juillet 2004StatutMembreDernière intervention25 juillet 201413 15 mars 2006 à 10:16
désolé pour le triple post mais le seveur m'a renvoyer 2 fois une erreur de page!!
@+
jlen
jlen100
Messages postés1606Date d'inscriptionsamedi 10 juillet 2004StatutMembreDernière intervention25 juillet 201413 15 mars 2006 à 10:14
Fred_ca_Pulse---> faut pas pousser le bouchon trop loin : quand tu dis que ta fonction existe depuis 50 ans au moins elle est donc antérieure à l'invention du Pascal (en 1971 je cois) et de l'introduction de la notion de pointeur dans ce langage (debut des années 80 si ma mémoire est bonne) Très fort!!!
@+
jlen
Fred_Ca_Pulse
Messages postés20Date d'inscriptionmercredi 15 mars 2006StatutMembreDernière intervention19 juin 2008 15 mars 2006 à 10:04
Bonjour à tous d'un nouveau sur le site !
Un petit commentaire pour f0xi du 12/02/2006.
Elle est effectivement très rapide ta fonction, mais elle marche pas bien, en effet la taille de destination va certainement changée et on obtient alors une chaîne dont la fin est non définie... pas très propre çà :)
Sur un modèle similaire j'ai écris :
function CaractereSupprimer( CSuppr : Char; const SChaine : String ) : String;
var
ILong, ILongInit : Longint;
PSource, PDest : PChar;
begin
ILong := Length( SChaine );
ILongInit := ILong;
SetLength( Result, ILong );
PSource := Pointer( SChaine );
PDest := Pointer( Result );
while ILong <> 0 do begin
if PSource^ <> CSuppr then
begin
PDest^ := PSource^;
Inc( PDest );
end;
Inc( PSource );
Dec( ILong );
end;
ILong := PDest - Pointer( Result );
if ILong <> ILongInit
then SetLength( Result, ILong );
end;
Ca fonctionne pour moi très bien depuis longtemps ... au moins 50 ans, c'est dire !!!
Mais je suis prêt à tout remettre en question pour une meilleure version...
... c'est comme çà qu'on avance !!!
walid2876
Messages postés49Date d'inscriptionmardi 26 avril 2005StatutMembreDernière intervention31 août 2008 14 févr. 2006 à 22:23
Salut Mon frere Medilias
D'abord il faut respecter les commentaires des membres car ils vous montre la bonne voix pour y aller vite et surement.
meme si tu dis que tu as 15 avec pascal ton code ne le dit pas
avec (tout mon respect)il faut toujours apprendre
ne viens pas en 2006 pour dire au gens comment utiliser une liste
enchainée dynamiquement ()!!!!!
et tu as choisis le pire exemple avec malheur ..
je te souhaite une bonne experience en programmation et profite des conseils des membres surtout qui vienne de la part de NONO et autres et malgré que je vis avec le pascal depuis la version 3 et j'ai devellopé des dizaine de Logiciel proffesionnel je telecharge tous les exemples du nono et d'autre pour apprendre plus et je dis toujours que j'ai pas engendré 50% du savoir programmer
jlen100
Messages postés1606Date d'inscriptionsamedi 10 juillet 2004StatutMembreDernière intervention25 juillet 201413 12 févr. 2006 à 18:35
salut,
foxi-->le principe des listes chainées est le suivant:
on decrit dans un record la structure de l'enregistrement auquel on ajoute un pointeur sur l'enregistrement suivant (dans le cas des listes doublement chainée on rajoute an plus un pointeur sur l'enregistrement précédent) si ce pointeur est à Nil on se trouve sur le dernier enregistrement .Le compilateur lui se moque totalemnt de savoir ce qu'il y a dedans,(pour lui c'est simplement un espace mémoire de 4 octets) ici il doit etre simplement du même type que l'enregistrement.( on pourrait même le déclarer, je pense, de type pointer.)
medelias-->quand je te dis que tu ne respectes pas les regles de base d'utilisation des pointeurs ce n'est pas innocent: une régle fondamentale est de toujours libérer la mémoire après utilisation des pointeurs en effet delphi ne le fait pas automatiquement
et tu te retrouves avec des fuites mémoires.
quand je dis qu'il n'est pas judicieux d'utiliser un pointeur pour stocker un caractére c'est déjà au niveau utilisation mémoire puisqu'il te faut mobiliser 5 octets pour 1 utile, ensuite en temps de process et d'occupation CPU : il faut appeler les routines de gestion de tas pour attribuer l'espace mémoire (et cela pour chaque caracteres)puis transférer le caractére et assigner le poinetur et si tu avais liberé la memoire les temps de traitement auraient certainement été multipliés par ~2.
je te rapelle également qu'une chaine de caracteres est un tableau et que l'on peut y acceder en donnant l'indice; en fait tu dis au programme d'aller chercher l'octet à l'adresse du tableau + l'offset (indice ou position du caractere) dans ce cas tu utilises implicitement un pointeur et en plus tu fais un transtypage. Notes également que c'est un excellent moyen pour passer des valeurs numériques dans une chaine de caracteres sans faire convertion.
Je dis également que ton exemple est mal choisi pour expliquer l'utilisation des listes chainées puisque tu ne montres ni comment on insère un élément dans la liste ni comment on le retire.(sans parler de la mauvaise utilisation des pointeurs)
Enfin j'ajouterai que l'utilisation des listes chainées est un reste du TP et qu'il vaut bien mieux , en général, lui préférer celle des Tlist qui bénéficient des methodes d'ajout et de suppression déjà implémentée , plus quelques propriétés fort utile.
je ne veux pas donner de leçons mais j'aimerais que ceux qui donnent le fasse à bon escient
@+
jlen
medelias
Messages postés18Date d'inscriptionmardi 28 octobre 2003StatutMembreDernière intervention12 mars 2006 12 févr. 2006 à 15:10
Salut;
je sais qu'il y a des O.O.M en executant cette fonction sur des textes car il y aura trop de new que de dispose mais comme j'avais déja mentionner c'est juste un exemple pour comprendre un petit peu le fonctionnement des pointeurs.
je vous prometterai tous un très beau logiciel à l'avenir.
Salut,
Medelias je reprend tes propos :"le seul défaut c'est qu'il n'y avait pas de commentaires." où tu es de mauvaise foi où tu n'as pas lu les commentaires de f0xi
il sont pourtant claire et sans appel :
-Fuites de mémoire en Méga Octets voir même Out Of Memory
-Et le temps d'execution qui est au moins 20 fois plus long
Et toi la seul chose que tu as retenu c'est le manque de commentaires ???? :-(
@+
Cirec
medelias
Messages postés18Date d'inscriptionmardi 28 octobre 2003StatutMembreDernière intervention12 mars 2006 12 févr. 2006 à 11:06
salut à vous tous,
delphi compiles ça :
type PReference = ^TReference;
TReference = record
Valeur : Char;
Svt : PReference;
end;
pour créer une liste chainée.
j'ai écris cette fonction pour des étudiants qui débuttent en pascal et surtout en pointeur et pour comprendre aussi la création d'une liste chainée. je ne vais pas utiliser quand même une telle fonction dans delphi là où il y a StringReplace, c'était juste à titre éducatif, le seul défaut c'est qu'il n'y avait pas de commentaires.
Chao
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 12 févr. 2006 à 09:11
de plus, je ne comprend pas que delphi puisse compiler cela :
type PReference = ^TReference;
TReference = record
Valeur : Char;
Svt : PReference;
end;
Svt pointeur sur record TReference qui contient lui meme un pointeur Svt pointeur sur record TReference qui contient egalement Svt pointeur sur record TReference qui contient lui aussi Svt pointeur sur record TReference qui contient encore une fois Svt pointeur sur record TReference qui contient a son tours Svt pointeur sur record TReference qui contient .......
je comprend maintenant d'ou viennent les 400Mo de charge.
et je ne pense pas que des en plus dipsose() y changeront quelque chose.
Mais bon voyons le bon coté des choses, c'est censé etre un exemple ? ok pas de problemes.
c'est bien un exemple de ce qu'il ne faut pas faire.
quelque part ... le defi est reussi. (sincerement)
errare humanum est, perseverare diabolicum,
cuiusvis hominis est errare, omnis homo perseverare. Sic.
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 12 févr. 2006 à 08:34
alors ...
premierement le fait de passer REF en parametre VAR c'est assé contraignant car on ne peu pas passer la valeur d'un edit ou label par exemple directement.
on doit créer une locale ou une globale pour traiter la chaine, ce qui est loin d'etre parfait comme utilisation.
en fait c'est un peu illogique meme de modifier la chaine envoyée et de renvoyer la chaine modifier en resultat de fonction ... autant travailler directement sur le resultat de la fonction car comme on l'a souvent dit, l'appel a result ne provoque pas de sortie prematurée de la fonction comme ne C/C++ ou autre langage.
moi j'aurais ecrit la fonction de cette façon (en remerciant florenth au passage pour m'avoir montrer comment utiliser les pointeurs)
-----
function SuppChar(const S : string; const C : char) : string;
var pS, pR : PChar;
begin
Result := '';
SetLength(Result, length(S));
pS := PChar(S);
pR := PChar(Result);
While pS^ <> #0 do begin
if pS[0] <> C then begin
pR[0] := pS[0];
Inc(pR);
end;
Inc(pS);
end;
end;
----
sur les performances y'a pas photo :
500000 requettes sur une chaine de 60 caracteres :
ma fonction : 1219ms (1.2 secondes)
StringReplace : 5328ms (5.3 secondes)
ta fonction : 22203ms (22.2 secondes)
50000 requettes sur une chaine de 255 caracteres :
ma fonction : 1641ms (1.6 secondes)
StringReplace : 22578ms (22.6 secondes)
ta fonction : Out Of Memory!
et encore je ne pousse pas le vice a donner la charge/fuite memoires relevées ...
aller si pourquoi pas ...
dans le premier test :
ma fonction : < 4 Ko
StringReplace : < 8 Ko
ta fonction : > 315Mo !
dans le deuxieme test :
ma fonction : < 8 Ko
StringReplace : < 10 Ko
ta fonction : dernier relevé a 453Mo avant OOM
sans vouloir critiquer ton travail ou parraitre medisant ou agressif, tes fonctions fonctionnent t'elles toujours aussi bien ? ou est-ce simplement l'oublis de faire un petit Bench (et un debugage) ?
La au moins ... c'est la preuve par les chiffres ...
une fonction qui bouffe 300 a 400Mo de memoire en quelque secondes ...
meme Quake 4 ne fait pas ça sur mon PC (quake 4 = 268Mo utilisé) et il fait bien plus de chose que de supprimer certains caracteres d'une chaine.
La remise en question n'est pas un echec, au contraire ça permet d'aller de l'avant.
Bref ... je note 0 car elle n'est pas fonctionnelle et pas du tout commentée.
l'effort et la ... le reste malheureusement ne suis pas.
ps : je suis developpeur amateur depuis 11 ans sur pascal et 5 sur delphi.
elguevel
Messages postés718Date d'inscriptionjeudi 19 décembre 2002StatutMembreDernière intervention22 novembre 20163 11 févr. 2006 à 10:04
Je trouve MEDIELAS assez nerveux, surtout que son code n'a pas été critiqué, on a juste dit qu'il existait une autre fonction plus simple.
Par contre sans entrer dans le code et sans méchanté (juré !) juste en observant le protoype :
function TForm1.SuppChar(var Ref: String; Ch: Char):String;
Tu laisse TForm1 ... je trouve pas çà propre pour qqn qui developpe depuis 15 ans et qui propose une fonction qui a pour but d'être intégré et utiliser tout de suite. Cela prouve aussi que tu as laissé ta fonction dans la classe de la page principal et non dans une unité ou une classe séparé. Donc maintenance et modularité = pas bon.
Enfin voila ... je m'arrette juste à cette ligne, mais je trouve que tu prend assez mal la critique.
++
medelias
Messages postés18Date d'inscriptionmardi 28 octobre 2003StatutMembreDernière intervention12 mars 2006 8 févr. 2006 à 13:33
Salut JLEN100,
j'ai vraiment adoré votre commentaire ça m'a fait penser à Matrix Revolution, pour que la communauté soit nombreuse je vous mettrez comme paramètre dans la fonction et puis dans un Repeat until False;
Merci à vous tous.
jlen100
Messages postés1606Date d'inscriptionsamedi 10 juillet 2004StatutMembreDernière intervention25 juillet 201413 8 févr. 2006 à 11:06
si tu n'acceptes pas les critiques c'est ton problème.
Maintenant comme ton code n'est pas un modèle de clareté médite sur cette maxime:
" Ce qui se conçoit aisément s'exprime facilement"
quand à me mettre dans ta fonction tu ne fairais que me multiplier!!
@+
jlen
medelias
Messages postés18Date d'inscriptionmardi 28 octobre 2003StatutMembreDernière intervention12 mars 2006 8 févr. 2006 à 10:26
Salut Nono40, et merci pour la remarque;
Ecoute JLEN100, je crois que c'est toi que je dois mettre dans la fonction et après ta décomposition je met en Free tout les variables et en Dispose tout les pointeurs et j'etteind mon PC
soit un peu gentil en donnant des conseils
a+ Nono40
cs_Nono40
Messages postés962Date d'inscriptionmercredi 3 avril 2002StatutMembreDernière intervention12 septembre 20062 8 févr. 2006 à 02:01
En plus il manque beaucoup de dispose() par rapport au nombre de new(). Grosse fuites de mémoires en perspective.
Niveau optimisation ce n'est pas terrible dans tous les cas.
( ca fait 16 ans que je bosse en pascal de TP3 à DElphi 2006 )
medelias
Messages postés18Date d'inscriptionmardi 28 octobre 2003StatutMembreDernière intervention12 mars 2006 8 févr. 2006 à 00:53
Hey les gars
mon but c'était de montrer comment travailler avec les pointeurs, je ne dis pas que je connais toutes les fonctions de Delphi mais à 90% donc n'essaye pas de m'exciter la prochaine fois, on est pas là pour donner des leçon de moral. ça fait plus de 15 ans que je developpe avec Pascal Objet et Delphi, so Shut uuuuuuuuuuuup
la prochaine fois essaye le mot MERCI, ça ne tues pas.
28 mai 2006 à 17:23
En mettant le caractère #0 au milieu d'une chaîne, fOxi, tu ne changes pas sa longueur. Exemple:
const s=#1#2#0#3#4;
Avec cet exemple de chaîne qui fait 5 caractères, le compilateur te dira que Length(s)=5 (la convention qu'un chaîne se termine au premier caractère #0 est vraie - et en partie seulement - pour le C mais pas en Delphi). De plus, même en C le fait qu'un char* contienne un \0 à un endroit ne signifie pas qu'il n'y a pas encore des données après, c'est juste une convention commode qu'utilisent ceux qui écrivent les API pour s'y retrouver.
Pour Delphi, une chaîne de type string est implémentée par une sorte d'interface sous-jacente (pour le ref-counting) avec un champ Length. C'est aussi le cas des tableaux dynamiques. C'est par exemple pour ça que si tu as:
var s:string;
@s ne pointe pas vers le premier caractère de la chaîne, mais vers cette fameuse interface de gestion des chaînes (idem pour les tableaux dynamiques). Tu peux calculer la taille en mémoire occupée par ce que Borland rajoutte (en plus des caractères) à une chaîne en calculant:
Integer(@s[1])-Integer(@s)
Je crois (mais ça demanderait à être revérifié) que ça fait 8 octets (tout simplement un entier integer contenant la longueur de la chaîne + un autre contenant le nombre de références à celle-ci).
Une version encore plus compacte de la fonction de Fred serait:
function SuppChar(const S : string; const C : char) : string;
var pS, pR : PChar; l : Integer;
begin
l := length(S)
SetLength(Result, l);
pS := PChar(S);
pR := PChar(Result);
While pS^ <> #0 do begin
if pS[0] <> C then begin
pR[0] := pS[0];
Inc(pR);
end else
Dec(l);
Inc(pS);
end;
SetLength(Result, l);
end;
Je ne pense pas que le Dec(l) soit trop gourmand en resources ^^
Dernière remarque, tu peux t'affranchir de faire Result:='' au début de la fonction car Delphi par défaut le fait pour toi (comme il le fait pour toutes les variables qui contiennent des interfaces "ref-counted").
16 avril 2006 à 15:57
alors tout simplement le rajout de :
function SuppChar(const S : string; const C : char) : string;
var pS, pR : PChar;
begin
Result := '';
SetLength(Result, length(S));
pS := PChar(S);
pR := PChar(Result);
While pS^ <> #0 do begin
if pS[0] <> C then begin
pR[0] := pS[0];
Inc(pR);
end;
Inc(pS);
end;
pR[0] := #0;
end;
et hop la chaine est finie...
15 mars 2006 à 11:02
C'était juste pour faire un peu d'ironie sur le temps passé à écrire ou à utiliser du code, et la possibilité qu'on puisse toujours avoir des bugs dedans ou qu'il existe une meilleure façon de l'écrire.
FRED
15 mars 2006 à 10:16
@+
jlen
15 mars 2006 à 10:14
@+
jlen
15 mars 2006 à 10:04
Un petit commentaire pour f0xi du 12/02/2006.
Elle est effectivement très rapide ta fonction, mais elle marche pas bien, en effet la taille de destination va certainement changée et on obtient alors une chaîne dont la fin est non définie... pas très propre çà :)
Sur un modèle similaire j'ai écris :
function CaractereSupprimer( CSuppr : Char; const SChaine : String ) : String;
var
ILong, ILongInit : Longint;
PSource, PDest : PChar;
begin
ILong := Length( SChaine );
ILongInit := ILong;
SetLength( Result, ILong );
PSource := Pointer( SChaine );
PDest := Pointer( Result );
while ILong <> 0 do begin
if PSource^ <> CSuppr then
begin
PDest^ := PSource^;
Inc( PDest );
end;
Inc( PSource );
Dec( ILong );
end;
ILong := PDest - Pointer( Result );
if ILong <> ILongInit
then SetLength( Result, ILong );
end;
Ca fonctionne pour moi très bien depuis longtemps ... au moins 50 ans, c'est dire !!!
Mais je suis prêt à tout remettre en question pour une meilleure version...
... c'est comme çà qu'on avance !!!
14 févr. 2006 à 22:23
D'abord il faut respecter les commentaires des membres car ils vous montre la bonne voix pour y aller vite et surement.
meme si tu dis que tu as 15 avec pascal ton code ne le dit pas
avec (tout mon respect)il faut toujours apprendre
ne viens pas en 2006 pour dire au gens comment utiliser une liste
enchainée dynamiquement ()!!!!!
et tu as choisis le pire exemple avec malheur ..
je te souhaite une bonne experience en programmation et profite des conseils des membres surtout qui vienne de la part de NONO et autres et malgré que je vis avec le pascal depuis la version 3 et j'ai devellopé des dizaine de Logiciel proffesionnel je telecharge tous les exemples du nono et d'autre pour apprendre plus et je dis toujours que j'ai pas engendré 50% du savoir programmer
12 févr. 2006 à 18:35
foxi-->le principe des listes chainées est le suivant:
on decrit dans un record la structure de l'enregistrement auquel on ajoute un pointeur sur l'enregistrement suivant (dans le cas des listes doublement chainée on rajoute an plus un pointeur sur l'enregistrement précédent) si ce pointeur est à Nil on se trouve sur le dernier enregistrement .Le compilateur lui se moque totalemnt de savoir ce qu'il y a dedans,(pour lui c'est simplement un espace mémoire de 4 octets) ici il doit etre simplement du même type que l'enregistrement.( on pourrait même le déclarer, je pense, de type pointer.)
medelias-->quand je te dis que tu ne respectes pas les regles de base d'utilisation des pointeurs ce n'est pas innocent: une régle fondamentale est de toujours libérer la mémoire après utilisation des pointeurs en effet delphi ne le fait pas automatiquement
et tu te retrouves avec des fuites mémoires.
quand je dis qu'il n'est pas judicieux d'utiliser un pointeur pour stocker un caractére c'est déjà au niveau utilisation mémoire puisqu'il te faut mobiliser 5 octets pour 1 utile, ensuite en temps de process et d'occupation CPU : il faut appeler les routines de gestion de tas pour attribuer l'espace mémoire (et cela pour chaque caracteres)puis transférer le caractére et assigner le poinetur et si tu avais liberé la memoire les temps de traitement auraient certainement été multipliés par ~2.
je te rapelle également qu'une chaine de caracteres est un tableau et que l'on peut y acceder en donnant l'indice; en fait tu dis au programme d'aller chercher l'octet à l'adresse du tableau + l'offset (indice ou position du caractere) dans ce cas tu utilises implicitement un pointeur et en plus tu fais un transtypage. Notes également que c'est un excellent moyen pour passer des valeurs numériques dans une chaine de caracteres sans faire convertion.
Je dis également que ton exemple est mal choisi pour expliquer l'utilisation des listes chainées puisque tu ne montres ni comment on insère un élément dans la liste ni comment on le retire.(sans parler de la mauvaise utilisation des pointeurs)
Enfin j'ajouterai que l'utilisation des listes chainées est un reste du TP et qu'il vaut bien mieux , en général, lui préférer celle des Tlist qui bénéficient des methodes d'ajout et de suppression déjà implémentée , plus quelques propriétés fort utile.
je ne veux pas donner de leçons mais j'aimerais que ceux qui donnent le fasse à bon escient
@+
jlen
12 févr. 2006 à 15:10
je sais qu'il y a des O.O.M en executant cette fonction sur des textes car il y aura trop de new que de dispose mais comme j'avais déja mentionner c'est juste un exemple pour comprendre un petit peu le fonctionnement des pointeurs.
je vous prometterai tous un très beau logiciel à l'avenir.
P.S. désolé tous pour la mauvaise humeur.
CHAO
12 févr. 2006 à 13:49
Medelias je reprend tes propos :"le seul défaut c'est qu'il n'y avait pas de commentaires." où tu es de mauvaise foi où tu n'as pas lu les commentaires de f0xi
il sont pourtant claire et sans appel :
-Fuites de mémoire en Méga Octets voir même Out Of Memory
-Et le temps d'execution qui est au moins 20 fois plus long
Et toi la seul chose que tu as retenu c'est le manque de commentaires ???? :-(
@+
Cirec
12 févr. 2006 à 11:06
delphi compiles ça :
type PReference = ^TReference;
TReference = record
Valeur : Char;
Svt : PReference;
end;
pour créer une liste chainée.
j'ai écris cette fonction pour des étudiants qui débuttent en pascal et surtout en pointeur et pour comprendre aussi la création d'une liste chainée. je ne vais pas utiliser quand même une telle fonction dans delphi là où il y a StringReplace, c'était juste à titre éducatif, le seul défaut c'est qu'il n'y avait pas de commentaires.
Chao
12 févr. 2006 à 09:11
type PReference = ^TReference;
TReference = record
Valeur : Char;
Svt : PReference;
end;
Svt pointeur sur record TReference qui contient lui meme un pointeur Svt pointeur sur record TReference qui contient egalement Svt pointeur sur record TReference qui contient lui aussi Svt pointeur sur record TReference qui contient encore une fois Svt pointeur sur record TReference qui contient a son tours Svt pointeur sur record TReference qui contient .......
je comprend maintenant d'ou viennent les 400Mo de charge.
et je ne pense pas que des en plus dipsose() y changeront quelque chose.
Mais bon voyons le bon coté des choses, c'est censé etre un exemple ? ok pas de problemes.
c'est bien un exemple de ce qu'il ne faut pas faire.
quelque part ... le defi est reussi. (sincerement)
errare humanum est, perseverare diabolicum,
cuiusvis hominis est errare, omnis homo perseverare. Sic.
12 févr. 2006 à 08:34
premierement le fait de passer REF en parametre VAR c'est assé contraignant car on ne peu pas passer la valeur d'un edit ou label par exemple directement.
on doit créer une locale ou une globale pour traiter la chaine, ce qui est loin d'etre parfait comme utilisation.
en fait c'est un peu illogique meme de modifier la chaine envoyée et de renvoyer la chaine modifier en resultat de fonction ... autant travailler directement sur le resultat de la fonction car comme on l'a souvent dit, l'appel a result ne provoque pas de sortie prematurée de la fonction comme ne C/C++ ou autre langage.
moi j'aurais ecrit la fonction de cette façon (en remerciant florenth au passage pour m'avoir montrer comment utiliser les pointeurs)
-----
function SuppChar(const S : string; const C : char) : string;
var pS, pR : PChar;
begin
Result := '';
SetLength(Result, length(S));
pS := PChar(S);
pR := PChar(Result);
While pS^ <> #0 do begin
if pS[0] <> C then begin
pR[0] := pS[0];
Inc(pR);
end;
Inc(pS);
end;
end;
----
sur les performances y'a pas photo :
500000 requettes sur une chaine de 60 caracteres :
ma fonction : 1219ms (1.2 secondes)
StringReplace : 5328ms (5.3 secondes)
ta fonction : 22203ms (22.2 secondes)
50000 requettes sur une chaine de 255 caracteres :
ma fonction : 1641ms (1.6 secondes)
StringReplace : 22578ms (22.6 secondes)
ta fonction : Out Of Memory!
et encore je ne pousse pas le vice a donner la charge/fuite memoires relevées ...
aller si pourquoi pas ...
dans le premier test :
ma fonction : < 4 Ko
StringReplace : < 8 Ko
ta fonction : > 315Mo !
dans le deuxieme test :
ma fonction : < 8 Ko
StringReplace : < 10 Ko
ta fonction : dernier relevé a 453Mo avant OOM
sans vouloir critiquer ton travail ou parraitre medisant ou agressif, tes fonctions fonctionnent t'elles toujours aussi bien ? ou est-ce simplement l'oublis de faire un petit Bench (et un debugage) ?
La au moins ... c'est la preuve par les chiffres ...
une fonction qui bouffe 300 a 400Mo de memoire en quelque secondes ...
meme Quake 4 ne fait pas ça sur mon PC (quake 4 = 268Mo utilisé) et il fait bien plus de chose que de supprimer certains caracteres d'une chaine.
La remise en question n'est pas un echec, au contraire ça permet d'aller de l'avant.
Bref ... je note 0 car elle n'est pas fonctionnelle et pas du tout commentée.
l'effort et la ... le reste malheureusement ne suis pas.
ps : je suis developpeur amateur depuis 11 ans sur pascal et 5 sur delphi.
11 févr. 2006 à 10:04
Par contre sans entrer dans le code et sans méchanté (juré !) juste en observant le protoype :
function TForm1.SuppChar(var Ref: String; Ch: Char):String;
Tu laisse TForm1 ... je trouve pas çà propre pour qqn qui developpe depuis 15 ans et qui propose une fonction qui a pour but d'être intégré et utiliser tout de suite. Cela prouve aussi que tu as laissé ta fonction dans la classe de la page principal et non dans une unité ou une classe séparé. Donc maintenance et modularité = pas bon.
Enfin voila ... je m'arrette juste à cette ligne, mais je trouve que tu prend assez mal la critique.
++
8 févr. 2006 à 13:33
j'ai vraiment adoré votre commentaire ça m'a fait penser à Matrix Revolution, pour que la communauté soit nombreuse je vous mettrez comme paramètre dans la fonction et puis dans un Repeat until False;
Merci à vous tous.
8 févr. 2006 à 11:06
Maintenant comme ton code n'est pas un modèle de clareté médite sur cette maxime:
" Ce qui se conçoit aisément s'exprime facilement"
quand à me mettre dans ta fonction tu ne fairais que me multiplier!!
@+
jlen
8 févr. 2006 à 10:26
Ecoute JLEN100, je crois que c'est toi que je dois mettre dans la fonction et après ta décomposition je met en Free tout les variables et en Dispose tout les pointeurs et j'etteind mon PC
soit un peu gentil en donnant des conseils
a+ Nono40
8 févr. 2006 à 02:01
Niveau optimisation ce n'est pas terrible dans tous les cas.
( ca fait 16 ans que je bosse en pascal de TP3 à DElphi 2006 )
8 févr. 2006 à 00:53
mon but c'était de montrer comment travailler avec les pointeurs, je ne dis pas que je connais toutes les fonctions de Delphi mais à 90% donc n'essaye pas de m'exciter la prochaine fois, on est pas là pour donner des leçon de moral. ça fait plus de 15 ans que je developpe avec Pascal Objet et Delphi, so Shut uuuuuuuuuuuup
la prochaine fois essaye le mot MERCI, ça ne tues pas.
7 févr. 2006 à 23:44
Et comme dirait l'autre :
À chacun mon tour ^_^
@+
Cirec
7 févr. 2006 à 23:41
cela ne fait même qu'une seule ligne
@+
jlen
7 févr. 2006 à 23:39
Et en plus tu te compliques la vie on peut faire la même chose en deux lignes de code,
certe pas avec les pointeurs mais bon
@+
Cirec
7 févr. 2006 à 23:36
Manifestement tu ne connais pas la fonction StringReplace de SysUtils :
Function StringReplace(const S, OldPattern, NewPattern: string;
Flags: TReplaceFlags): string;
Et en plus tu te compliques la vie on peut faire la même chose en deux lignes de code
@+
Cirec