| Autor |
Beitrag |
MagicRain
      
Beiträge: 154
WinXp, Win8, iOS
Delphi 7, Lazarus Pascal, Delphi 10.2 Starter, NetBeans Java
|
Verfasst: Do 25.06.09 19:19
Hallo ich möchte folgendes mit einem langen String machen....
Quelltext 1: 2: 3: 4: 5:
| C92917D2E4D98789EE51928EECA075E8K3NDI45JKS90OMLJD56JLSDJ7LSK6DK .........
wird zu:
C929-17D2-E4D9-8789-EE51 ...................... |
Habe es mal so versucht aber das kalppt nicht so ganz wie ich es möchte
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.Button1Click(Sender: TObject); var a,b:String; begin a := Edit1.Text; a[5] :='-'; Edit2.Text := a; end; |
Wäre nett wenn mir jemand da irgendwie helfen kann?!?!
MfG Moderiert von Narses: Topic aus Sonstiges (Delphi) verschoben am Do 25.06.2009 um 20:00
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Do 25.06.09 19:29
Etwa so in der Art: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| var orginal, neu: String; begin i := 1; j := 1; while i <= length(orginal) do begin neu[j] := orginal[i];
inc(j);
if (i mod 5 = 0) and (i <> length(orginal)) then begin neu[j] := '-'; inc(j); end;
inc(i); end; |
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Do 25.06.09 19:33
is zwar jetzt n bissal code mit pseudocode vermischt aber ich denke es wird dir helfen:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.Button1Click(Sender: TObject); var orginal, neu: String; begin original := Edit1.Text; i := 1; j := 1; während i+4 <= länge(orginal) do begin kopiere von der stelle i bis i+4 den text aus original in neu; füge am ende von neu ein '-' an; inkrementiere i um 4; end; end; |
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
MagicRain 
      
Beiträge: 154
WinXp, Win8, iOS
Delphi 7, Lazarus Pascal, Delphi 10.2 Starter, NetBeans Java
|
Verfasst: Do 25.06.09 19:49
Oh man danke euch
MfG
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 25.06.09 19:53
Oder gleich in eine Funktion gepackt:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| function InsertGivenChar(const Src: string; InsChr: char; InsertAfter: integer): string; var i,j: integer; begin SetLength(Result,Length(Src) + Length(Src) div InsertAfter); i := 1; j := 1; while i <= Length(Src) do begin Result[j] := Src[i]; inc(j); if ((i mod InsertAfter) = 0) and (i < Length(Src)) then begin Result[j] := InsChr; inc(j); end; inc(i); end; end; |
[edit] Denkfehler korrigiert, das kommt davon, wenn man direkt im Editor tippt. [/edit]
Zuletzt bearbeitet von DeddyH am Fr 26.06.09 20:03, insgesamt 2-mal bearbeitet
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Do 25.06.09 22:07
darf ich fragen warum ihr beide die Copyfunktion von Delphi so verschmäht?
lg elundril
(Die Befehlssyntax ist folgende: anyString := Copy(anotherString, Index, Count);)
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Do 25.06.09 22:57
Hallo,
nicht die Copyfunktion wird verschmäht, sondern die durch Copy erforderlich werdenden Stringverkettungen.
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 26.06.09 08:19
Wenn es um Geschwindigkeit geht:
Da sollte man dann erstens keine while-Schleife nehmen, bei der in jedem Durchlauf Length aufgerufen wird und zweitens nicht auf Strings indiziert zugreifen, da bei diesem zeichenweisen Zugriff jedes Mal der Referenzzähler überprüft wird.
@ DeddyH: Deine Methode verschluckt das letzte Zeichen, nämlich das mit dem Index Length(Src), denn da brichst du schon ab, stattdessen steht da ein zufälliges Zeichen drin.
Wenn die Stringlänge ein Vielfaches der Länge der Einzelteile, hier also 4, ist, dann geht es auch so: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| function InsertHyphens4A(const AText: AnsiString): AnsiString; var i, TextLen: Integer; Src, Dst: PAnsiChar; begin TextLen := Length(AText); SetString(Result, nil, TextLen + Pred(TextLen div 4)); Src := PChar(AText); Dst := PChar(Result); for i := 1 to Pred(TextLen div 4) do begin PLongWord(Dst)^ := PLongWord(Src)^; Inc(Src, 4); Inc(Dst, 4); Dst^ := '-'; Inc(Dst); end; PLongWord(Dst)^ := PLongWord(Src)^; end; | Oder allgemeiner und auch für Unicode in D2009, dafür langsamer: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| function InsertHyphens(const AText: string; AChars: Integer): string; var i, TextLen: Integer; Src, Dst: PChar; begin TextLen := Length(AText); SetString(Result, nil, TextLen + Pred(TextLen div AChars)); Src := PChar(AText); Dst := PChar(Result); for i := 1 to Pred(TextLen div AChars) do begin CopyMemory(Dst, Src, AChars * SizeOf(Char)); Inc(Src, AChars); Inc(Dst, AChars); Dst^ := '-'; Inc(Dst); end; CopyMemory(Dst, Src, AChars * SizeOf(Char)); end; |
|
|
MagicRain 
      
Beiträge: 154
WinXp, Win8, iOS
Delphi 7, Lazarus Pascal, Delphi 10.2 Starter, NetBeans Java
|
Verfasst: Fr 26.06.09 12:25
So danke euch für die ganzen Beiträge richtig klasse aber ich habe die Lösung dann doch gefunden viel einfacher!
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| Insert('-',STRING1,5); Insert('-',STRING1,10); Insert('-',STRING1,15); Insert('-',STRING1,20);
SetLength(STRING1, 24); |
MfG
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 26.06.09 12:28
Klar, das passt für diesen Fall, aber ist nicht variabel, falls man das nochmal braucht 
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 26.06.09 12:36
Und ist natürlich sehr viel langsamer, also nur geeignet, wenns nur einmal oder so ausgeführt wird. In einer Schleife wäre sowas kaum sinnvoll. 
|
|
MagicRain 
      
Beiträge: 154
WinXp, Win8, iOS
Delphi 7, Lazarus Pascal, Delphi 10.2 Starter, NetBeans Java
|
Verfasst: Fr 26.06.09 13:01
Ja da muss ich euch rechtgeben  nun habe ich ja viele lösungen danke
MfG
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 26.06.09 13:10
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| Function InsertDashes(S: String): String; var X: Integer; SP,DP: PChar; Begin SetLength(Result, Length(S) + Length(S) div 4); SP := @S[1]; DP := @Result[1]; For X := 1 to Length(S) do Begin DP^ := SP^; Inc(SP); Inc(DP); If (X and 3) = 0 then Begin DP^ := '-'; Inc(DP); end; end; end; |
Die Übersetzung nach ASM überlasse ich dem geneigten Leser ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Fr 26.06.09 19:10
Wartbarkeit, Lesbarkeit, Robustheit, Portierbarkeit gegen unnütze Performance macht hier keinen Sinn. For-Schleife mit Insert o.ä. ist dagegen einfach zu verstehen, praktisch selbsterklärend und macht am wenigsten Annahmen über den Aufbau von Strings.
Wartbarkeit:
Wenn mit Assembler oder Pointern gearbeitet wird: Ist schwieriger zu debuggen, verstehen und erweitern (vor allem von anderen)
Lesbarkeit:
Assembler praktisch unlesbar. Mit Pointern ist es etwas besser aber nicht besonders elegant.
Robustheit:
Schnell mal einen Bug programmiert durch undurchdachter Zugriff über Pointer:
InsertDashes: Macht einen ungültigen Zugriff auf [1], wenn der Eingabestring leer ist.
InsertHyphens4A/InsertHyphens: Schreibt auf PChar(''), wenn der Eingabestring leer ist.
Portierbarkeit:
Assembler ist überhaupt nicht portabel. Falls mit Pointern und/oder CopyMemory gearbeitet wurde: Vorsicht geboten bei Transition von String zu UnicodeString -> Code macht möglicherweise Annahmen über die Struktur von String.
Fazit:
Die Prozedur, die oben keine Pointerarithmetik verwendet ist InsertGivenChar. Die einzige Prozedur, die hier sicher gegen Zugriffsverletzung ist. Allerdings durch die Verwendung von mehreren Indizes etwas unübersichtlich, und enthält einen Denkfehler: Die Prozedur funktioniert nicht wie gewünscht, wenn Length(Src) mod InsertAfter = 0 bei Length(Src)>0
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 26.06.09 20:03
Stimmt, hab es oben verbessert.
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Fr 26.06.09 21:32
Oh..Oh..Oderso (Kurz und Knapp):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| Function UnterteileString (Const aString : string; aTeilerZeichen : Char; aAbstand : Integer) : String; Var i : Integer;
Begin i := aAbstand+1; Result := aString; While i <= Length (Result) do begin Insert (aTeilerZeichen,Result,i); inc (i, aAbstand+1); End End; |
_________________ Na denn, dann. Bis dann, denn.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 26.06.09 21:37
delfiphan hat folgendes geschrieben : | | Wartbarkeit, Lesbarkeit, Robustheit, Portierbarkeit gegen unnütze Performance macht hier keinen Sinn. For-Schleife mit Insert o.ä. ist dagegen einfach zu verstehen, praktisch selbsterklärend und macht am wenigsten Annahmen über den Aufbau von Strings. |
For-Schleife mit Insert ist dagegen: ultra lahmarschig, strapaziert den Memory Manager unnötig, ist einfach unelegant!
delfiphan hat folgendes geschrieben : | Wartbarkeit:
Wenn mit Assembler oder Pointern gearbeitet wird: Ist schwieriger zu debuggen, verstehen und erweitern (vor allem von anderen) |
Dafür gibt es Kommentare ... sofern diese nötig sein sollte
delfiphan hat folgendes geschrieben : | Lesbarkeit:
Assembler praktisch unlesbar. Mit Pointern ist es etwas besser aber nicht besonders elegant. |
ASM ja, Pointer sind dagegen ein warer Genuss. Je kürzer die Anweisung, desto klarer wird sie.
delfiphan hat folgendes geschrieben : | Robustheit:
Schnell mal einen Bug programmiert durch undurchdachter Zugriff über Pointer:
InsertDashes: Macht einen ungültigen Zugriff auf [1], wenn der Eingabestring leer ist. |
Falsch: Wenn Input-String leer ist, wird zwar [1] als Adresse aufgelöst, jedoch nie zugegriffen.
delfiphan hat folgendes geschrieben : | InsertHyphens4A/InsertHyphens: Schreibt auf PChar(''), wenn der Eingabestring leer ist.
Portierbarkeit:
Assembler ist überhaupt nicht portabel. Falls mit Pointern und/oder CopyMemory gearbeitet wurde: Vorsicht geboten bei Transition von String zu UnicodeString -> Code macht möglicherweise Annahmen über die Struktur von String. |
Meine Pointer-Version IST Portabel
delfiphan hat folgendes geschrieben : | Fazit:
Die Prozedur, die oben keine Pointerarithmetik verwendet ist InsertGivenChar. Die einzige Prozedur, die hier sicher gegen Zugriffsverletzung ist. |
Jain ... InsertDashes ist auch sicher gegen Zugriffsverletzungen, trotz dem Pointer-Arithmetik verwendet wird. Was jedoch bei meiner Routine wichtig ist, ist die Tatsache, dass man genau wissen sollte, was jeder Befehl tut. Ist also nichts, was man unkonzentriert schreiben sollte ...
delfiphan hat folgendes geschrieben : | | Allerdings durch die Verwendung von mehreren Indizes etwas unübersichtlich, und enthält einen Denkfehler: Die Prozedur funktioniert nicht wie gewünscht, wenn Length(Src) mod InsertAfter = 0 bei Length(Src)>0 |
Und genau diese doppelten Index-Berechnungen machen InsertGivenChar nicht optimal, da ständig Sachen doppelt und dreifach berechnet werden.
Kommt halt immer drauf an, was man speziell will.
Geht Kürzer:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| Function UnterteileStringShorterSource (Const S : string; C : Char; A : Integer) : String; Var i : Integer; Begin Result := S; i := (Length(S) div A) * A + 1; While i > 1 do begin Insert (C, Result, i); Dec(i, A); End; End; |
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Oreaden
      
Beiträge: 16
|
Verfasst: Fr 26.06.09 23:04
juten Morgen,
sehe ich das richtig, 'n Wettbewerb? Da will ich doch auch zwei Zeilen in den Ring werfen
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:
|
procedure InsStr(Var aStr: string; At: integer; Chr: char); var LengthIdx,RunIdx : integer; TmpStr : string; SourceChar, DestinationChar: PChar; begin LengthIdx := length(aStr); if (LengthIdx = 0) or (LengthIdx < at) then exit; TmpStr := aStr; setlength(aStr, LengthIdx + LengthIdx div at); SourceChar := @TmpStr[at]; DestinationChar := @aStr[at]; RunIdx := at; while RunIdx < LengthIdx do begin if RunIdx mod at = 0 then begin inc(DestinationChar); DestinationChar^ := chr; end; inc(RunIdx); inc(SourceChar); inc(DestinationChar); DestinationChar^:= SourceChar^; end; end; |
vielleicht gefällts
Oreaden
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Fr 26.06.09 23:16
@BenBE: Ich werde nicht versuchen, dich zu ändern  Du darfst gerne deine eigene Meinung behalten. Ich bleibe bei meiner Meinung.
"@S[1]": Okay, gibt vielleicht keine Zugriffsverletzung, aber führt dazu, dass du keine Range-Checks mehr verwenden darfst. Kann man ja ausschalten, würdest du jetzt sagen. Klar, es gibt für alles eine Lösung. Aber in meiner täglichen Arbeit merke ich einfach, dass solche Kleinigkeiten mit der Zeit mühsam sind. Wenn die Hälfte nicht da steht oder eine Menge Annahmen im Code stecken, die nur der Originalautor kennt, dann knallt's halt öfters mal und man muss rumwerkeln, bis es endlich läuft. Im schlimmsten Fall muss ich eine Änderung in Fremd-Code machen, und beim nächsten Update darf ich wieder nachprüfen, ob der Fehler in zwischen schon gefixt ist, oder ob ich die Änderung wieder machen muss.
Ich will in erster Linie ein Programm, eine Prozedur, eine Komponente, was auch immer, das nicht ständig rumzickt sondern einfach funktioniert (Vorausgesetzt ich habe sie richtig verwendet. Bei falscher Verwendung bzw. Gefahr darf sie mich gerne darauf aufmerksam machen).
Kommentare: Guter Code kommt mit sehr wenig Kommentaren aus. Ausserdem machen die wenigsten Leute gute Kommentare. Besser ist es, wenn der Code selbsterklärend ist.
Portabilität: Da gibt es einen fliessenden Übergang zwischen portabel und nicht portabel. Von Delphi 2007 zu Delphi 2009 mag dein Code ohne Änderung laufen. Aber Pointers gibt es nicht überall.
Wenn ich bei einem Code-Review eine Assemblerlösung für dieses Problem sehe würde ich es zurückschicken.
Wie auch immer. Ich fand es nur ironisch, dass hier jeder versuchte, einen schnelleren Code als der vorherige zu schreiben. Dabei war keine Lösung überhaupt wirklich funktionsfähig. Deine übrigens auch nicht, wenn der String zum Beispiel 8-stellig ist.
Aber lassen wir's gut sein. Ich wollte nur darauf Aufmerksam machen, dass hier evtl. die falschen Prioritäten gesetzt werden. Es gibt viele verschiedene Programmier-Philosophien in der Literatur. Unix Philsophie, Extreme Programming Philsophie (YAGNI, OAOO, SPOT), etc.. Meistens heisst es, dass Code-Optimierung an letzter Stelle kommt. Und ich bin damit zu einem grossen Teil einverstanden.
Zuletzt bearbeitet von delfiphan am Fr 26.06.09 23:30, insgesamt 1-mal bearbeitet
|
|
MagicRain 
      
Beiträge: 154
WinXp, Win8, iOS
Delphi 7, Lazarus Pascal, Delphi 10.2 Starter, NetBeans Java
|
Verfasst: Fr 26.06.09 23:29
Was ist denn jetzt hier passiert krieg ?  aber danke euch allen!!!
MfG
|
|
|