Fred_Ca_Pulse
Messages postés20Date d'inscriptionmercredi 15 mars 2006StatutMembreDernière intervention19 juin 2008
-
16 août 2006 à 09:44
Fred_Ca_Pulse
Messages postés20Date d'inscriptionmercredi 15 mars 2006StatutMembreDernière intervention19 juin 2008
-
17 août 2006 à 11:05
Bonjour à tous
Pour otimiser mon code, j'ai voulu transformer en procédure la fonction de remplacement que j'utilise depuis longtemps déjà :
function CaractereRemplacer( CSource, CDestination : Char; const SChaine : String ) : String;
var
ILong : Longint;
Source, Dest : PChar;
begin
ILong := Length( SChaine );
SetLength( Result, ILong );
Source := Pointer( SChaine );
Dest := Pointer( Result );
while ILong <> 0 do begin
if Source^ = CSource
then Dest^ := CDestination
else Dest^ := Source^;
Inc( Source );
Inc( Dest );
Dec( ILong );
end;
end;
Son équivalent en procédure me semblait assez évident :
procedure CaractereRemplacerP( CSource, CDestination : Char; var SChaine : String );
var
ILong : Longint;
Source : PChar;
begin
ILong := Length( SChaine );
Source := Pointer( SChaine );
while ILong <> 0 do begin
if Source^ = CSource
then Source^ := CDestination;
Inc( Source );
Dec( ILong );
end;
end;
Mais, bien sûr , çà ne marche pas comme je voudrais :
j'obtiens une merveilleuse "Violation d'accès" lorqu'un caractère doit être remplacé par Source^ := CDestination
J'ai bien pensé à un problème de référencement des chaînes et j'ai donc ajouté la ligne
"UniqueString( SChaine );" en début de procédure :
çà fonctionne alors mais les performances ne sont plus à la hauteur !
Si vous avez une petite îdée sur la question, merci de m'en faire part.
DRJEROME
Messages postés436Date d'inscriptionjeudi 9 janvier 2003StatutMembreDernière intervention 5 février 2015 16 août 2006 à 17:09
pouah...j'avais celle là...mais elle est certainement plus lente que toutes les vôtres (je vais tester) :
<hr />
procedure CaractereRemplacer1( CSource, CDestination : Char;var SChaine : String);
var
Source,Dest : PChar;
Resultat:String;
begin
Resultat:=SChaine;
Dest := @Resultat[1];
Source := @SChaine[1];
while Source^<>^@ do
begin
if Source^ = CSource then Dest^ := CDestination;
Inc( Source );
Inc( Dest);
end;
SChaine:=Resultat;
end;
<hr />
DRJEROME
Messages postés436Date d'inscriptionjeudi 9 janvier 2003StatutMembreDernière intervention 5 février 2015 16 août 2006 à 17:27
sinon celle de Cirec peut se transformer avec des "var" :
<hr />
Procedure CaractereRemplacer( CSource, CDestination : Char; var SChaine : String; var result : String );
var
ILong : Longint;
Source, Dest : PChar;
begin
ILong := Length( SChaine );
SetLength( Result, ILong );
Source := Pointer( SChaine );
Dest := Pointer( Result );
while ILong <> 0 do begin
if Source^ = CSource
then Dest^ := CDestination
else Dest^ := Source^;
Inc( Source );
Inc( Dest );
Dec( ILong );
end;
end;
<hr />
DRJEROME
Messages postés436Date d'inscriptionjeudi 9 janvier 2003StatutMembreDernière intervention 5 février 2015 16 août 2006 à 17:30
on peut aussi transformer la mienne ainsi :
<hr />
procedure CaractereRemplacer1( CSource, CDestination : Char;var SChaine : String; var Resultat:String);
var
Source,Dest : PChar;
begin
Resultat:=SChaine;
Dest := @Resultat[1];
Source := @SChaine[1];
while Source^<>^@ do
begin
if Source^ = CSource then Dest^ := CDestination;
Inc( Source );
Inc( Dest);
end;
end;
<hr />
mais j'ai la flemme de tester tout ça (je vais chez le dentiste)
Cà m'a l'air plein de bonnes idées ...
mais chez moi çà plante sur une "Erreur de vérification d'étendue" à la fin de la chaîne S[i] lorsque i = Length + 1
... j'ai l'option "Vérification des limites" activée !
En la désactivant çà marche ...
En fait les options de compilation changent énormément la performance d'exécution.
Je vais étudier un peu plus la chose.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Fred_Ca_Pulse
Messages postés20Date d'inscriptionmercredi 15 mars 2006StatutMembreDernière intervention19 juin 2008 17 août 2006 à 11:05
Rebonjour à tous, voilà ma petite synthèse à moi :
- le passage de fonction en procédure n'est pas concluant : bug d'accès à la variable dans certains cas, et pas de gain de performance
- on peut visiblement faire mieux que ma fonction initiale ( merci f0xi )
- les options de compilations "Vérifier les limites" et "Verifier les débordements" influent non seulement sur les erreurs détectées, mais aussi sur les performances
J'ai donc écrit une nouvelle procédure inspirée de celle de f0xi mais évitant le problème de vérification et je l'ai comparée à ma fonction initiale selon les options de compilation :
function CaractereRemplacer1( CSource, CDestination : Char; const SChaine : String ) : String;
var
ILong : Longint;
Source, Dest : PChar;
begin
ILong := Length( SChaine );
SetLength( Result, ILong );
Source := Pointer( SChaine );
Dest := Pointer( Result );
while ILong <> 0 do begin
if Source^ = CSource
then Dest^ := CDestination
else Dest^ := Source^;
Inc( Source );
Inc( Dest );
Dec( ILong );
end;
end;
function CaractereRemplacer2( CSource, CDestination : Char; const SChaine : String ) : String;
var
ILong, I : Longint;
PDest : PChar;
begin
ILong := Length( SChaine );
SetLength( Result, ILong );
if ILong > 0 then
begin
PDest := Pointer( Result );
I := 1;
repeat
PDest[ 0 ] := SChaine[ I ];
if PDest[ 0 ] = CSource
then PDest[ 0 ] := CDestination;
Inc( PDest );
Inc( I );
until I > ILong;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
F, A, B, V1, V2 : Int64;
STest, SResult1, SResult2 : String;
I : Longint;
begin
Windows.QueryPerformanceFrequency( F );
STest := 'Test de remplacement de caractères';
Windows.QueryPerformanceCounter( A );
for I := 1 to 10000000 do
SResult1 := CaractereRemplacer1( 'e', 'o', STest );
Windows.QueryPerformanceCounter( B );
V1 := Trunc( ( B - A ) / F * 1000 );
Windows.QueryPerformanceCounter( A );
for I := 1 to 10000000 do
SResult2 := CaractereRemplacer2( 'e', 'o', STest );
Windows.QueryPerformanceCounter( B );
V2 := Trunc( ( B - A ) / F * 1000 ); ShowMessage( 'Résultat V1 ' + SResult1 + #13 + 'Temps V1 ' + IntToStr( V1 ) + #13 + 'Résultat V2 ' + SResult2 + #13 + 'Temps V2 ' + IntToStr( V2 ) );
end;
Je tourne sous XP SP2 avec Delphi 7 sur un Pentium D 2.8 Ghz.
Voici mes résultats :
L+D = activation Limites + Débordements
D = activation seulement des Débordements
L = activation seulement des Limites
Rien = ni l'un, ni l'autreLa meilleure est bien la V2, mais avec des fluctuations étranges lors de l'activation de seulement une des 2 options testées.
Voilà une bien étrange conclusion pour une histoire débutée sur une simple question d'algorithmie.
Enfin, je suis déjà content : j'ai toujours une fonction, mais elle va plus vite !
...
Le problème suivant sera de déterminer combien de temps il va falloir que cette nouvelle fonction tourne en continue pour justifier le temps passé à la modifier ?
Avis aux amateurs ... A+