Entwickler-Ecke
Sonstiges (Delphi) - String umdrehen
morphi - Fr 25.02.05 17:51
Titel: String umdrehen
Ich möchte den Text aus der Textbox Edit2 in Edit1 umgedreht haben also das aus Wurzel "lezruW" wird. z.B. ich bin anfäger
danke Morphi
delfiphan - Fr 25.02.05 17:57
:welcome:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Var A, B : String; I : Integer; begin A := 'Wurzel'; B := A; For I := 1 to length(A) do B[length(A)-I+1] := A[I]; end; |
uall@ogc - Fr 25.02.05 18:03
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| varr A : String; I : Integer; B : char; begin A := 'Wurzel'; For I := 1 to length(A) do begin b := a[i]; A[I] := A[length(A)-i+1]; A[length(A)-i+1] := b; end; end; |
für lange strings ist das besser da kein 2ter string angelegt werden muss
BeniSchindler - Fr 25.02.05 18:03
Oder :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| Var A, B : String; Index : Integer; begin A := 'Wurzel'; B := ''; For Index := length(A) downto 1 do B := B + A[Index]; end; |
uall@ogc - Fr 25.02.05 18:12
das ist bis jetzt die schlechteste variante da delphi da immer einen neuen string erstellen muss
delfiphan - Fr 25.02.05 18:15
So werden ständig neue Strings aneinandergehängt :O
//Edit: Ok stimmt glaub ich nicht ganz.. :\ auf jeden Fall ist es performancemässig am besten, wenn du nicht ständig was zu einem String dazufügst. Wenn die Länge eines Strings am Anfang schon gegeben ist, dann solltest du das auch am Anfang festlegen.
jasocul - Fr 25.02.05 18:18
Dürfte noch schneller sein:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Var A, B : String; Index : Integer; laenge : Integer; begin A := 'Wurzel'; laenge := Length(A); SetLength(B,laenge); For Index := laenge downto 1 do B[laenge+1-Index] := A[Index]; end; |
uall@ogc - Fr 25.02.05 18:20
jasocul
1.) hast du 2 strings -> das mag ich schon net ;>
2.) downto schleife langsamer als for to schleife
3.) speichert delphi die länge eh in einem register (ebx) von daher isses egal ob du das vorher in eine variable auslagerst
delfiphan - Fr 25.02.05 18:22
Wer hat Lust, das ganze jetzt noch in Assembler zu schreiben :D
delfiphan - Fr 25.02.05 18:26
Ich denke sowieso nicht, dass length(S) langsamer ist als ne gewöhnliche Variable zu lesen. Length wird nicht in einen call verwandelt, oder? Zu mindest nicht bei Pascal-Strings.
uall@ogc - Fr 25.02.05 18:27
length(s) wird bei einer schleifenvariable in EBX geschrieben, sollte also genausoschnell / shcneller sein
da delphi auch die variable in EBX packen würde
delfiphan - Fr 25.02.05 18:29
Also ich meinte eher grundsätzlich so... Bzw. beispielsweise in der For-Schleife drin:
Delphi-Quelltext
1: 2:
| For I := 1 to length(A) do B[length(A)-I+1] := A[I]; |
uall@ogc - Fr 25.02.05 18:32
meine variante hatte sogar noch nen bug
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| var s: string; i, l: integer; b: char; begin s := 'das ist ein test'; l := length(s); for i := 1 to l div 2 do begin b := s[i]; s[i] := s[l-i+1]; s[l-i+1] := b; end; form1.caption := s; end; |
ich muss nur die hälfte des strings machen ;>
jasocul - Fr 25.02.05 18:34
Neue Variante und Kommentare:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| Var A : String; B : Char; Index : Integer; Ende : Integer; laenge : Integer; begin A := 'Wurzel'; laenge := Length(A); Ende := (laenge div 2)+1; For Index := laenge downto ende do begin B := A[laenge+1-Index]; A[laenge+1-Index] := A[Index]; A[Index] := B; end; end; |
Da ich die Länge mehrfach benötige macht es durchaus Sinn. Ich hätte allerdings auch auf A[0] zugreifen können. Da kann es aber zu Problemen mit AnsiStrings kommen.
Die neue Variante hat auch nur noch einen String.
Eine for..downto ist meistens schneller als for..to. Dazu gab es auch schon Threads, weil Delphi das auch in diese Richtung optimiert, wenn es möglich ist.
Die Schleife läuft jetz nur noch über die Hälfte des Strings.
Wenn jetzt noch was verbessert werden soll, läuft es auf Assembler raus.
//EDIT:
Mist. Hätte ich nicht kommentiert wäre ich schneller gewesen als uall@ogc :wink:
delfiphan - Fr 25.02.05 18:39
morphi hat folgendes geschrieben: |
ich bin anfäger |
Morphi wird Freude haben :)
Eben genau das war meine Frage: Ob denn length(S) in einen Function-Call oder bei normalen Strings direkt in ein S[0] übersetzt wird.
//Edit: Hui, ist aber schwach, es gibt tatsächlich einen Function Call. Hätte jetzt fast gedacht, dass das zu S[0] optimiert wird.
Sprint - Fr 25.02.05 18:41
Titel: Re: String umdrehen
morphi hat folgendes geschrieben: |
Ich möchte den Text aus der Textbox Edit2 in Edit1 umgedreht haben also das aus Wurzel "lezruW" wird. z.B. ich bin anfäger |
Delphi-Quelltext
1:
| Edit1.Text := AnsiReverseString(Edit2.Text); |
Unter Delphi 7 gibt es die Funktion AnsiReverseString. Unter Delphi 5 nicht. Bei Delphi 6 weiß ich es nicht.
jasocul - Fr 25.02.05 18:43
Dann jetzt nochmal für Morphi:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.Button1Click(Sender: TObject); Var A : String; B : Char; Index : Integer; Ende : Integer; laenge : Integer; begin A := Edit2.Text; laenge := Length(A); Ende := (laenge div 2)+1; For Index := laenge downto ende do begin B := A[laenge+1-Index]; A[laenge+1-Index] := A[Index]; A[Index] := B; end; Edit1.Text := A; end; |
Dominique - Fr 25.02.05 18:45
Ist zwar nicht von mir, sondern von Ralph Friedmann (TeamB), aber bestimmt eine der schnellsten Methoden:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| function Reverse(S: string): string; var I: integer; L: integer; P: PChar; Q: PChar; begin L := Length(S);
if L = 0 then Exit;
SetLength(Result, L);
P := PChar(Result); Q := PChar(S) + (L - 1);
repeat P^ := Q^; Inc(P); Dec(Q); until Q = PChar(Pointer(S)); end; |
und du nutzt es dann so:
Delphi-Quelltext
1:
| Edit1.Text := Reverse(Edit2.Text); |
Dominique - Fr 25.02.05 18:51
Titel: Re: String umdrehen
Sprint hat folgendes geschrieben: |
Unter Delphi 7 gibt es die Funktion AnsiReverseString. Unter Delphi 5 nicht. Bei Delphi 6 weiß ich es nicht. |
leider ist's mit stringfunktionen bis delphi 7 nicht so üppig.
ein tip an morphi: guck doch zwischendurch mal in die delphi hilfe :roll:
delfiphan - Fr 25.02.05 18:53
Ok, wir geben uns geschlagen :) Ist ca. 4 mal schneller als Jasocul's korrigierte Methode von uall ;)
// Edit: und ca. 20% schneller als meine, wenn man dort noch die Länge zuvor in einer Variablen speichert ;(
uall@ogc - Fr 25.02.05 19:13
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| procedure change(s: pchar); asm push edx push ecx push ebx push esi xor edx, edx @goon: mov cl, [eax+edx] inc edx test cl, cl jnz @goon dec edx dec edx mov esi, edx shr esi, 1
xor ecx, ecx @goon2: test esi, esi jz @ende mov bl, [eax+ecx] xchg byte ptr [eax+edx], bl mov byte ptr[eax+ecx], bl
dec esi dec edx inc ecx jmp @goon2 @ende: pop esi pop ebx pop ecx pop edx end;
procedure TForm1.FormCreate(Sender: TObject); var s: string; begin memo1.lines[0] := 'das ist ein test hahahahaha'; s := memo1.lines[0]; change(pchar(s)); form1.caption := s; end; |
geht aber net bei hardcoded strings :)
jasocul - Fr 25.02.05 19:14
Das dürfte nicht so schnell zu toppen sein. *applaus*
opfer.der.genauigkeit - Fr 25.02.05 19:54
Sicherlich nicht getoppt, aber ich wollt auch was dazu beitragen.
*senfdazugeb* :wink:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| edtReverseOutput.Text := res;
sIn := edtReverseInput.Text; len := Length(sIn);
SetLength(sOut, Len);
for i := 1 to Len do begin pchar(integer(pointer(sOut)) + len - i)^ := pchar(integer(pointer(sIn)) + i - 1)^; end;
edtReverseOutput.Text := sOut; |
Moderiert von
raziel: Code- durch Delphi-Tags ersetzt.
delfiphan - Sa 26.02.05 00:52
Also die Assemblerfunktion funzt bei mir nicht ;)
Übrigens
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| For I := 1 to length(S) do begin P^ := Q^; Inc(P); Dec(Q); end; |
Wird übersetzt in (hier ist anfänglich eax = length(S)):
Quelltext
1: 2: 3: 4: 5: 6:
| mov dl,[esi] mov [ebx],dl inc ebx dec esi dec eax jnz -$09 |
Man hat zwar schlussendlich eine Kopie des Strings, aber performancemässig lässt es sich wohl nicht mehr toppen. Das ist vor allem schnell, weil die Indices nicht ständig neu errechnet werden müssen (im Stil von "length-i+1" oder sowas).
opfer.der.genauigkeit - Sa 26.02.05 04:20
@morphi
Bedien dich, es sind genügend Vorschläge da.
Ich glaube man erlebt nicht so oft, dass sich die Leute nen kleinen Kontestliefern um die
beste Lösung zu finden.. :lol:
//Edit: Achja :welcome:
IngoD7 - Sa 26.02.05 11:38
Titel: Re: String umdrehen
Ohne irgendwelche Geschwindigkeitsräusche mit ausleben zu wollen, plädiere ich auch für ein einfaches niedliches ReverseString.
delfiphan - Sa 26.02.05 12:05
@uall: Ich glaub Morphi hat Angst gekriegt wegen dem Assembler :x Jetzt kommt er nicht mehr zurück ;)
uall@ogc - Sa 26.02.05 12:32
Delphi-Quelltext
1: 2: 3: 4: 5:
| @goon: mov cl, [eax+edx] inc edx test cl, cl jnz @goon |
das ist meine length funktion
wie gesgat das funzt nur bei strings wo man schreibzugrif drauf hat, bei den hard codes strings gehts net weil die in dem code drin stehen der aber nur READ_EXECUTE rechte hat, nen viretual protect solltedas lösen können
ansonsten erstellt delphi vorher immer eine kopie des strings
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| dec edx dec edx mov esi, edx shr esi, 1 xor ecx, ecx @goon2: test esi, esi jz @ende mov bl, [eax+ecx] xchg byte ptr [eax+edx], bl mov byte ptr[eax+ecx], bl dec esi dec edx inc ecx jmp @goon2 @ende: pop esi pop ebx pop ecx pop edx |
delfiphan - Sa 26.02.05 12:52
Ok, deine Funktion mag unter allen Funktionen - die keine Kopien erstellen - die schnellste sein. Aber wer will denn schon die Reihenfolge eines 10mb Strings umdrehn? Sogar bei 10mb würd ich kurz ne Kopie erstellen. Kommt natürlich immer auf den einzelnen Fall an. Aber auch bei 10mb sehe ich Speed vor Speichergebrauch.
Die Schleife hier:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| For I := 1 to length(S) do begin P^ := Q^; Inc(P); Dec(Q); end; |
ist bedeutend schneller als das ganze Assembler Zeug.
uall@ogc - Sa 26.02.05 13:13
ok ich geb mich geschlagen, würde eh eine fertige funktion nehmen anstatt assembler zeugs ^^
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!