Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi ReverseString für ältere Delphi-Versionen (https://www.delphipraxis.net/144590-reversestring-fuer-aeltere-delphi-versionen.html)

Wolfgang Mix 11. Dez 2009 15:28


ReverseString für ältere Delphi-Versionen
 
Wie aus diesem Thread http://www.delphipraxis.net/internal...109571#1109571
hervorgeht, fehlt die Funktion ReverseString in älteren Delphi-Versionen. Daher lege ich als Ersatz
meine Komposition noch einmal hier ab, damit man sie auch findet.

Delphi-Quellcode:
//Wolfgang Mix - Delphi-PRAXiS
function ReverseString (MyString: string): string;
var HelpString:string;
    i:integer;
begin
  HelpString:='';
  for i:=length(MyString) downto 1 do
  HelpString:=HelpString+MyString[i];
  result:=HelpString;
end;

//Usage
procedure TForm1.Button1Click(Sender: TObject);
var String1,String2:String;
begin
  String1:=Edit1.Text;
  String2:=ReverseString(String1);
  Edit2.Text:=String2;
end;
Gruß

Wolfgang

jfheins 11. Dez 2009 15:39

Re: ReverseString für ältere Delphi-Versionen
 
Ich hätte da noch eine schnellere Version im Kopf:
Delphi-Quellcode:
// (c) 2009 jfheins - member of Delphi-PRAXiS
function ReverseString (str: string): string;
var
  i, len:integer;
begin
  len := length(str);
  setlength(Result, len);
  for i := len downto 1 do
    Result[i] := str[len - i + 1];
end;
Optimierungen:
1. Wegfall des Hilfsstrings
2. Statt der Verkettung von String und Char jetzt mit setlength und Zugriff per Index

Wobei ich mich (ein weiteres mal) frage, ob das nicht etwas sehr trivial ist - die Code-Library sollte ja gerade Qualität statt Quantität enthalten ;)

Wolfgang Mix 11. Dez 2009 15:52

Re: ReverseString für ältere Delphi-Versionen
 
Ich gebe Dir Recht, soon Ding coden wir in 5 Minuten,
aber Anfänger haben mit noch einfacheren Dingen Schwierigkeiten.
Andererseits hat Embarcadingsbums noch trivialere Funktionen,
wenn ich da an Tommorrow und Yesterday denke :mrgreen:

Gruß

Wolfgang

himitsu 11. Dez 2009 22:08

Re: ReverseString für ältere Delphi-Versionen
 
Delphi-Quellcode:
Function ReverseString(Const Text: String): String;
Var L: Integer;
  S, D: PChar;
Begin
  L := Length(Text) - 1;
  SetLength(Result, L + 1);
  S := PChar(Text);
  D := PChar(Result) + L;
  For L := L downto 0 do Begin
    D^ := S^;
    Inc(S);
    Dec(D);
  End;
End;
Ihr wißt aber, daß die/unsere Ansi-Varianten nur mit Singelbyte-Zeichensätzen richtig arbeiten?


Und weil ich grad mal 'nen Sekündchen lang Lange Weile hatte: :oops:
Delphi-Quellcode:
Function ReverseString(Const Text: AnsiString): AnsiString; Overload;
  ASM
    PUSH EDI
    PUSH ESI
    PUSH EDX
    PUSH EAX
    XCHG EAX, EDX
    TEST EDX, EDX
    JZ   @@ZeroSet
    SUB  EDX, 4
    MOV  EDX, [EDX]
    @@ZeroSet:
    CALL _LStrSetLength
    POP  ESI
    POP  EDI
    MOV  EDI, [EDI]
    SUB  EDI, 4
    MOV  ECX, ESI
    TEST ECX, ECX
    JZ   @@Exit
    SUB  ECX, 4
    MOV  ECX, [ECX]
    //XOR  EAX, EAX
    //@@Loop:
    //MOV  DL, [ESI + EAX]
    //MOV  [EDI + ECX], DL
    //INC  EAX
    //LOOP @@Loop
    //@@Exit:
    PUSH ECX
    MOV  EAX, ECX
    AND  EAX, $3
    ADD  EDI, EAX
    SHR  ECX, 2
    // TEST ECX, ECX  // wenn SHR das Zero-Flag nicht setzt, dann dieses einfügen
    JZ   @@None4
    XOR  EAX, EAX
    @@Loop4:
    MOV  EDX, [ESI + EAX * 4]
    BSWAP EDX
    MOV  [EDI + ECX * 4], EDX
    INC  EAX
    LOOP @@Loop4
    @@None4:
    POP  EAX
    MOV  ECX, EAX
    AND  ECX, $3
    JZ   @@Exit
    AND  EAX, $FFFFFFFC
    @@Loop:
    MOV  DL, [ESI + EAX]
    MOV  [EDI + ECX + 1], DL
    INC  EAX
    LOOP @@Loop
    @@Exit:
    POP  ESI
    POP  EDI
  End;

{$IFDEF UNICODE}
Function ReverseString(Const Text: UnicodeString): UnicodeString; Overload;
  ASM
    PUSH EDX
    PUSH EAX
    XCHG EAX, EDX
    TEST EDX, EDX
    JZ  @@ZeroSet
    SUB EDX, 4
    MOV EDX, [EDX]
    @@ZeroSet:
    CALL _UStrSetLength
    POP ESI
    POP EDI
    MOV EDI, [EDI]
    SUB EDI, 2
    MOV ECX, ESI
    TEST ECX, ECX
    JZ  @@Exit
    SUB ECX, 4
    MOV ECX, [ECX]
    XOR EAX, EAX
    @@Loop:
    MOV DX, [ESI + EAX * 2]
    MOV [EDI + ECX * 2], DX
    INC EAX
    LOOP @@Loop
    @@Exit:
  End;
{$ENDIF}

Function ReverseString(Const Text: WideString): WideString; Overload;
  ASM
    PUSH EDX
    PUSH EAX
    XCHG EAX, EDX
    TEST EDX, EDX
    JZ  @@ZeroSet
    SUB EDX, 4
    MOV EDX, [EDX]
    SHR EDX, 1
    @@ZeroSet:
    CALL _WStrSetLength
    POP ESI
    POP EDI
    MOV EDI, [EDI]
    SUB EDI, 2
    MOV ECX, ESI
    TEST ECX, ECX
    JZ  @@Exit
    SUB ECX, 4
    MOV ECX, [ECX]
    SHR ECX, 1
    XOR EAX, EAX
    @@Loop:
    MOV DX, [ESI + EAX * 2]
    MOV [EDI + ECX * 2], DX
    INC EAX
    LOOP @@Loop
    @@Exit:
  End;
Und weil ich einfach zu doof bin, um die Funktionen der System-Unit aufzurufen
(ich hasse es, daß die Namen der System.pas nicht mit der System.dcu und der CPU-Anzeige übereinstimmen)
Delphi-Quellcode:
Procedure _LStrSetLength(Var Text: AnsiString; Len: Integer);
  Begin
    SetLength(Text, Len);
  End;

{$IFDEF UNICODE}
Procedure _WStrSetLength(Var Text: WideString; Len: Integer);
  Begin
    SetLength(Text, Len);
  End;
{$ENDIF}

Procedure _UStrSetLength(Var Text: UnicodeString; Len: Integer);
  Begin
    SetLength(Text, Len);
  End;

Wolfgang Mix 11. Dez 2009 22:18

Re: ReverseString für ältere Delphi-Versionen
 
@himitsu:
Zitat:

Und weil ich einfach zu doof bin, um die Funktionen der System-Unit aufzurufen
Tröste dich, das geht mir fast immer so.
Ausserdem ist es viel spannender, die Probleme selber zu lösen. :)

Gruß

Wolfgang

Wolfgang Mix 11. Dez 2009 22:36

Re: ReverseString für ältere Delphi-Versionen
 
Inzwischen denke ich, dass das Thema trotz aller Simplizität doch Wert ist,
in der CodeLib untergebracht zu werden.

turboPASCAL 11. Dez 2009 22:37

Re: ReverseString für ältere Delphi-Versionen
 
Hi,

ich verstehe euren Programmiertechnischen Aufwand nicht. :duck:

Delphi-Quellcode:
function ReverseAnsiString(const s: Ansistring): Ansistring;
var i : integer;
begin
  for i := length(s) downto 1 do
    Result := Result + s[i];
end;

himitsu 11. Dez 2009 23:12

Re: ReverseString für ältere Delphi-Versionen
 
Vielleicht, weil dein Code nicht wirklich gut arbeitet?

Und weil er über 20 Mal langamer ist, als mein Pascal-Code? :angel2:
Also inkl. dem Result:=''; ansonsten bremst es je Aufruf natürlich noch extremer ab, da ja der Resultstring immer größer wird.
(der Code von jfheins ist dagegen 3 Mal schneller, bei einem 10 Zeichen langem String, wärend dein Code eine expotentiell steigende Zeit zur Stringlänge hat und unsere Codes arbeiten linear)

Dein String ist nicht initialisiert.
Delphi-Quellcode:
function ReverseAnsiString(const s: Ansistring): Ansistring;
var i : integer;
begin
  Result := '';
  for i := Length(s) downto 1 do
    Result := Result + s[i];
end;
probier es mal aus ... du wirst ganz schön erstaunt sein
Delphi-Quellcode:
var S, S2: AnsiString;
  i: Integer;

S := '123';
for i := 0 to 9 do
begin
  S2 := ReverseString(S);
  ShowMessage(S2);
end;

turboPASCAL 11. Dez 2009 23:35

Re: ReverseString für ältere Delphi-Versionen
 
Zitat:

Dein String ist nicht initialisiert.
Muss man auch nicht. In der Function wird Result automatisch geleert.
sicherlich, guter Style ist es nicht.

Mit der Geschwindigkeit kann es schon so sein, da Setlengt den Stringzähler
" s[0] := x " (klappt ja bei Delphi nur noch per Umweg [SetLength]) den ben. Platz
gleich reserviert ohne ihn jedes mal erneut um eins zu erhöhen.

Vill. bin ich auch nur zu müde um richtig nachdenken zu können. ;)

himitsu 11. Dez 2009 23:44

Re: ReverseString für ältere Delphi-Versionen
 
Nein, beim Result ist es was Anderes, der wird nicht automatisch initialisiert, so wie es bei normalen Variablen der Fall ist.

Wie gesagt, probier es einfach mal aus.
ShowMessage zeigt nacheinander dieses an:

1. Aufruf: Result/S=321
2. Aufruf: Result/S=321321
3. Aufruf: Result/S=321321321
4. Aufruf: Result/S=321321321321
5. Aufruf: Result/S=321321321321321
6. Aufruf: Result/S=321321321321321321
7. Aufruf: Result/S=321321321321321321321
8. Aufruf: Result/S=321321321321321321321321
9. Aufruf: Result/S=321321321321321321321321321
10. Aufruf: Result/S=321321321321321321321321321321


Dieser Code:
Delphi-Quellcode:
function ReverseString(const s: Ansistring): Ansistring;
var i : integer;
begin
  for i := Length(s) downto 1 do
    Result := Result + s[i];
end;

var S, S2: AnsiString;
  i: Integer;

S := '123';
for i := 0 to 9 do
begin
  S2 := ReverseString(S);
  ShowMessage(S2);
end;
enspricht intern eigentlich diesem:
Delphi-Quellcode:
procedure ReverseString(const s: Ansistring; var Result: Ansistring);
var i : integer;
begin
  for i := Length(s) downto 1 do
    Result := Result + s[i];
end;

var S, S2: AnsiString;
  i: Integer;

S := '123';
for i := 0 to 9 do
begin
  ReverseString(S, S2);
  ShowMessage(S2);
end;
Und nun erkennt man bestimmt auch, warum es dort nicht funktioneren kann.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:59 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz