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/)
-   -   StringReplace und doppelte Zeichen (https://www.delphipraxis.net/105530-stringreplace-und-doppelte-zeichen.html)

Opa 23. Dez 2007 19:33


StringReplace und doppelte Zeichen
 
Nach dem ich erkennen musste das <StringReplace> nicht immer richtig funktioniert
StringReplace(S,#32#32,#32) kommt es zu Fehlern.
Hier mal eine Lösung: (Uppercase habe ich weggelassen, ich brauche das nicht für mein PRG)
Code:
function KillDoppelZeichenToZeichen(S:string;C:Char):string;
var
  I : integer;
begin
  if Length(S) < 2 then
  begin
    Result := S;//Zufrieden
   exit;
  end;
  Result := '';
  I := Length(S);
  repeat
    if (S[I] = C) and (I > 1) then
    begin
        while (S[I-1] = C) and (I > 1) do
        begin
          dec(I);
          if I < 2 then break; //Vertippt nicht 1 sonder I
        end;
     end;
    Result := S[I]+Result;
   dec(I);
  until I < 1;
end;
MFG

himitsu 23. Dez 2007 19:48

Re: StringReplace und doppelte Zeichen
 
Wie nicht richtig funktioniert?
was für Fehler?

und wie sollte deine Funktion da helfen, bzw. wie soll man die nutzen?


ja und wozu ist der leere Try-Except-Block?

if Length(S) < 2 then exit; : was pasiert wenn S nur 1 Zeichen lang ist?

[add]
was is'n dat für'n komischer Denglisch-Funktionsname?

[add2]
if 1 < 2 then break; : 1 ist immer kleiner als 2 (aber das sollte dir Delphi auch schon gesagt haben)

Opa 23. Dez 2007 20:10

Re: StringReplace und doppelte Zeichen
 
1: Der Name es viel mir nichts besseres ein. (Ist doch egal)
2: Der Try Except der kann weg (gestört hatte der aber nicht)
3 Wie die Helfen kann dann gib mal ein:
caption :=
_KillDoppelZeichenToZeichen(‚xxDasxlebenxxso schönxxxxseinxwennxesxnichtxxxxwelchexgebenxwürdex xxdiexxherummekelnxxmüssen.’,’x’);
Das Ding geht und fertig. Kannst den Mod sagen: Das Du es löschen möchtes und gut ist!

X = <Leer-Zeichen>
MFG :duck:

Matze 23. Dez 2007 20:28

Re: StringReplace und doppelte Zeichen
 
Hallo,

was funktioniert denn bei StringReplace nicht? Bei mir geht alles einwandfrei, zumindest konnte ich kein Fehlverhalten feststellen. ;)

Grüße

Opa 23. Dez 2007 21:43

Re: StringReplace und doppelte Zeichen
 
Ja wirklich? Dann versuch das mal mit (xxDasxxxxxLebenx ist schön)
Code:
var
  Flags  : TReplaceFlags;
  OK : boolean;
  S : string;
begin
  S:='xxDasxxxxxLebenx ist schön';{x = ggf. Leer-Zeichen}
  Flags := [rfReplaceAll, rfIgnoreCase];
//  S := StringReplace(S,'xx','x',Flags); // Erg = xDasxxxLebenx ist schön
    S:= KillDoppelZeichenToZeichen(S,'x'); //Erg = xDasxLebenx ist schön (so will ich das haben)
  Caption := S;
Mfg

grenzgaenger 23. Dez 2007 22:16

Re: StringReplace und doppelte Zeichen
 
und wo liegt das problem???

Delphi-Quellcode:
var
  Flags  : TReplaceFlags;
  OK : boolean;
  S : string;
begin
  S:='xxDasxxxxxLebenx ist schön';{x = ggf. Leer-Zeichen}
  Flags := [rfReplaceAll, rfIgnoreCase];
  S := StringReplace(S,'xx','x',Flags); // Erg = xDasxxxLebenx ist schön
//  xDasxxxLebenx ist sch÷n
   writeln(s);
   readln;
end.
das macht delphi doch optimal und genau richtig :-) . je zwei xx werden mit einem x ersetzt... also beispiel

xxDas --> xDas

und das kommt doch genau raus, oder brauch ich eine brille? :roll:

übrigens xxxxx = 5 x = 2x ersatz plus 1x übrig also xxx

himitsu 23. Dez 2007 22:22

Re: StringReplace und doppelte Zeichen
 
Dann hast du String Replace nicht verstanden, denn das ist genauso wie StringReplace geplant ist, also völlig richtig.

Recursionen gibt es nicht.

Delphi-Quellcode:
S := 'xxxxxxxxxx';
//    1122334455

S := StringReplace(S, 'xx', 'x', [rfReplaceAll]);

// S = 'xxxxx'
//      12345
weil rate mal was hier sonst passieren würde
Delphi-Quellcode:
S := 'xxx';
S := StringReplace(S, 'x', 'xx', [rfReplaceAll]);
das ergäbe bei Rekursion nicht 'xxxxxx' sondern einen unendlichlangen String aus x (also OutOfMemory oder wen unendlich Speicher vorhanden, dann würde dies Funkion nie ferig werden)


PS:
DoppelzeichenZuZeichen
EntferneDoppelZeichen
EntferneMehrfachZeichen
KillDupeChars
...

Dax 23. Dez 2007 22:24

Re: StringReplace und doppelte Zeichen
 
Ich glaube, Opa sucht eine Funktion, die der Regex r/x{2,}/x/g folgt...

Opa 23. Dez 2007 22:49

Re: StringReplace und doppelte Zeichen
 
Ich suche nicht ich schreibe es mir selber. :coder:

Was StringReplace macht ist mir (Jetzt) klar und auch wie er es macht.
Was ich brauchte, war eine >Einfache Funktion< Die alle doppelten Zeichen (die fortlaufend sind) löscht bis auf eines.

Das Problem war, dass ich in Dateinamen doppelte Leerzeichen (evtl. x Leerzeichen, fortlaufen) hatte. Ein Leerzeichen wollte ich aber erhalten. Und nachdem ich mir StringReplace angeschaut hatte, stellte ich fest dass, dieses nicht geht. Also hatte ich mir eine eigenen Funktion geschrieben. Und weil bald Weihnachten ist, dachte ich das auch andere diese Funktion gebrauchen können. Ich mach das nie wieder! Ich merke schon das dieses nicht erwünscht ist. Bin halt ein alter Mann und denke wirres Zeug. :spin2:

Sollte es in Delphi eine Funktion sein (die ich nicht kenne) die viele Zeichen durch aber mindestens 1 ersetzt/behält. Bitte mitteilen.

MFG

grenzgaenger 23. Dez 2007 23:42

Re: StringReplace und doppelte Zeichen
 
tja, aber für 'ne einfache funktion recht komplex geworden...

guck dir mal den folgenden code an ... etwas kompakter, macht das selbe, denke ist besser für weiterentwicklungen...

grüsse und noch schöne weihnachten

Delphi-Quellcode:
function ReplaceDChar(Quelle: string; aChar: char): string;
var
 i: integer;
begin
 result := '';
 for i := 1 to length(quelle) do
  if (length(result)=0) or (quelle[i]<>result[length(result)]) or (aChar<>result[length(result)]) then
   result := result + quelle[i];
end;

Dax 23. Dez 2007 23:47

Re: StringReplace und doppelte Zeichen
 
Und der hier dürfte letztlich am schnellsten sein:
Delphi-Quellcode:
function ReduceMultiples(const s: string; c: char): string;
var i, pos: Integer;
begin
  SetLength(result, Length(s));
  pos := 1;
  for i := 1 to Length(s) do
  begin
    if (i = 1) or (result[pos-1] <> s[i]) then
    begin
      result[pos] := s[i];
      Inc(pos);
    end;
  end;
  SetLength(result, pos-1);
end;

Opa 24. Dez 2007 01:16

Re: StringReplace und doppelte Zeichen
 
S:='xxDasxxxxxLebenx ist schön';
@DAX
S:='xxDasxxxxxLebenx ist schönxx';
Caption := ReduceMultiples(S,'x');//Erg ='xxDasxxxxxLebenx ist schön' (geht nicht)
Der Name ist schön. Und schnell ist die function ggf. auch nur NICHT RICHTIG

@grenzgaenger
Caption := ReplaceDChar(S,'x'); //Erg OK, und sieht schöner aus. Bin mir nur nicht sicher ob sie schneller als meine ist
Und der Name ist auch besser.

Mfg

Dax 24. Dez 2007 01:33

Re: StringReplace und doppelte Zeichen
 
Ja, da hat sich ein Tippfehler eingeschlichen;) Ist korrigiert.

Opa 24. Dez 2007 02:10

Re: StringReplace und doppelte Zeichen
 
@ DAX
Immer noch richtig. C wird nicht genutzt. Du machst so alle doppelten Platt auch (z.B. ss) :wink:

MFG

Dax 24. Dez 2007 02:13

Re: StringReplace und doppelte Zeichen
 
Ach, mist^^ Es sei dem geneigten Leser überlassen, das noch zu ändern :mrgreen: Auf mich wartet eine Matratze.. :angel:

Opa 24. Dez 2007 02:19

Re: StringReplace und doppelte Zeichen
 
if (I = 1) or (Result[P-1] <> S[I]) or (Result[P-1] <>C)
So geht das ich gehe jetz auch ins Bett :mrgreen:

MFG
PS.: Kein Ergeiz, geht doch glatt Pennen. :corky:

Opa 24. Dez 2007 10:12

Re: StringReplace und doppelte Zeichen
 
Opa - 00-00-00-156 - Ich x bin x der x schnellste x Hase x der der Welt
grenzgenger - 00-00-00-125 - Ich x bin x der x schnellste x Hase x der der Welt
DAX - 00-00-00-031 - Ich x bin x der x schnellste x Hase x der der Welt
----------------------------------------------------
Opa - 00-00-00-172 - Ich x bin x der x schnellste x Hase x der der Welt
grenzgenger - 00-00-00-125 - Ich x bin x der x schnellste x Hase x der der Welt
DAX - 00-00-00-016 - Ich x bin x der x schnellste x Hase x der der Welt
----------------------------------------------------
Opa - 00-00-00-172 - Ich x bin x der x schnellste x Hase x der der Welt
grenzgenger - 00-00-00-125 - Ich x bin x der x schnellste x Hase x der der Welt
DAX - 00-00-00-031 - Ich x bin x der x schnellste x Hase x der der Welt

DAX, deine ist wirklich die Schnellste, Respekt.
Meine kommt dann in die Tonne :zwinker:
MFG

DP-Maintenance 24. Dez 2007 10:50

DP-Maintenance
 
Dieses Thema wurde von "Matze" von "Tools rund um Delphi" nach "Neuen Beitrag zur Code-Library hinzufügen" verschoben.
Ich schiebe das nun hierhin. Es könnte für andere auch brauchbar sein.
Um ein Delphi-Tool geht es sowieso nicht. ;)

himitsu 24. Dez 2007 17:15

Re: StringReplace und doppelte Zeichen
 
zum Original-Code:
Delphi-Quellcode:
function EntferneDoppelZeichen(Const S: String; C: Char): String;
var
  i : integer;
begin
  Result := '';
  i := Length(S);
  repeat
    if S[i] = C then
      while (i > 1) and (S[i - 1] = C) do // erst Wertebereich für i prüfen
      begin                                // und dann auf S zugreifen
        dec(I);
        if i < 2 then break; // i und nicht 1
      end;
    //Result := S[i] + Result;
    Insert(S, S[i], 1);
    dec(i);
  until i < 1;
end;
und hier mal was Kurzes (nicht sehr schnell, aber bestimmt schneller als'es Original, aber zumindestens ein schön kompakter Code)

schnell genug?
Delphi-Quellcode:
function EntferneDoppelZeichen(Const S: String; C: Char): String;
var
  i : integer;
begin
  Result := S;
  for i := Length(S) downto 2 do
    if (S[i] = C) and (S[i - 1] = C) then
      Delete(S, i, 1);
end;
schneller:
Delphi-Quellcode:
Function ReduceMultiples(Const S: String; C: Char): String;
  Var Pi, Po, Pe: PChar;
    Cm: Char;

  Begin
    Result := S;
    If Result = '' Then Exit;
    Pi := @Result[1];
    Pe := Pi + Length(Result);
    Inc(Pi);
    Po := Pi;
    Cm := Result[1];
    While Pi < Pe do Begin
      If (Pi^ <> Cm) or (Pi^ <> C) Then Begin
        Inc(Po);
        Cm := Pi^;
      End;
      Inc(Pi);
      Po^ := Pi^;
    End;
    SetLength(Result, Po - @Result[1] + 1);
  End;
ein bissl Langsamer, aber so ginge es och noch:
Delphi-Quellcode:
Function ReduceMultiples(Const S: String; C: Char): String;
  Var Pi, Po, Pe: PChar;

  Begin
    Result := S;
    If Result = '' Then Exit;
    Pi := @Result[1];
    Pe := Pi + Length(Result);
    Inc(Pi);
    Po := Pi;
    While Pi < Pe do Begin
      If (Pi^ <> (Po - 1)^) or (Pi^ <> C) Then Inc(Po);
      Inc(Pi);
      Po^ := Pi^;
    End;
    SetLength(Result, Po - @Result[1] + 1);
  End;
notfalls ließe sich dat Vorletzte noch leicht in ASM umwandeln.

alzaimar 24. Dez 2007 18:07

Re: StringReplace und doppelte Zeichen
 
Hier
Delphi-Quellcode:
Function RemoveCharRepetitions(Const aText: String; aChar: Char): String;
Var
  i, j: Integer;
  c: Char;

Begin
  setLength(Result, Length(aText));
  If Length(aText)=0 Then Exit;
  j := 1;
  c := aText[1];
  Result[1] := c;
  For i := 2 To Length(aText) Do
    If aText[i] <> c Then Begin
      Inc(j);
      c := aText[i];
      Result[j] := c;
    End;
  SetLength(Result, j);
End;

Dax 24. Dez 2007 18:18

Re: StringReplace und doppelte Zeichen
 
aChar wird bei dir aber auch nicht verwendet :stupid:

grenzgaenger 24. Dez 2007 18:19

Re: StringReplace und doppelte Zeichen
 
der code von DAX ist schneller, weil er die länge des strings zu anfang setzt, bei meinen aktuellen code, wird bei jeden hinzufügen eines zeichens der speicher umgeschichtet. das kannst auf zweierlei arten lösen
  • mit setlengh, zu anfang und am schluss, wie bei DAX oder
  • in dem du aus String 'n ShortString machst, dann ist es aber auf 255 zeichen beschränkt

grüss und noch 'n schönes weihnachten

GG, der mit den dynamischen arrays noch immer nicht umgehen kann ;-)

grenzgaenger 24. Dez 2007 19:54

Re: StringReplace und doppelte Zeichen
 
Zitat:

Zitat von Opa
Opa - 00-00-00-156 - Ich x bin x der x schnellste x Hase x der der Welt
grenzgenger - 00-00-00-125 - Ich x bin x der x schnellste x Hase x der der Welt
DAX - 00-00-00-031 - Ich x bin x der x schnellste x Hase x der der Welt
----------------------------------------------------
Opa - 00-00-00-172 - Ich x bin x der x schnellste x Hase x der der Welt
grenzgenger - 00-00-00-125 - Ich x bin x der x schnellste x Hase x der der Welt
DAX - 00-00-00-016 - Ich x bin x der x schnellste x Hase x der der Welt
----------------------------------------------------
Opa - 00-00-00-172 - Ich x bin x der x schnellste x Hase x der der Welt
grenzgenger - 00-00-00-125 - Ich x bin x der x schnellste x Hase x der der Welt
DAX - 00-00-00-031 - Ich x bin x der x schnellste x Hase x der der Welt

DAX, deine ist wirklich die Schnellste, Respekt.
Meine kommt dann in die Tonne :zwinker:
MFG

@Opa: ich kann dein Ergebnis nicht nachvollziehen...
Variante Opa: 35 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante DAX: 10 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

Variante alzaimar: 9 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

Variante Grenzgaenger: 28 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

die Variante von DAX ist zwar die zweit schnellste, aber vom Ergebnis her...

grenzgaenger 24. Dez 2007 20:07

Re: StringReplace und doppelte Zeichen
 
habe das ganze mal, statt als Funktion als Procedure impelentiert...

hier das Ergebnis:
Code:
Variante Opa: 35 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante DAX: 10 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

Variante alzaimar: 9 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

Variante Grenzgaenger: 11 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante himitsu: 10 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen
und der Code:
Delphi-Quellcode:
procedure ReplaceDChar(Var Quelle: string; aChar: char);
var
  i, j: integer;
begin
  j := 1;
  for i := 2 to length(quelle) do
   if (quelle[i]<>quelle[j]) or (aChar<>quelle[j]) then
   begin
    j := j + 1;
    quelle[j] := quelle[i];
   end;
  setlength(quelle, j);
end;

alzaimar 24. Dez 2007 20:11

Re: StringReplace und doppelte Zeichen
 
Ick bin ja auch blöd: Übergebe ein Zeichen, dessen doppelte Vorkommen weggeschnippelt werden sollen, und dann wird dieses Zeichen ignoriert...

Delphi-Quellcode:
Function RemoveCharRepetitions(Const aText: String; aChar: Char): String;
Var
  i, j: Integer;
  c: Char;

Begin
  setLength(Result, Length(aText));
  If Length(aText)=0 Then Exit;
  j := 1;
  c := aText[1];
  Result[1] := c;
  For i := 2 To Length(aText) Do
    If (c<>aChar) or (aText[i] <> c) Then Begin
      Inc(j);
      c := aText[i];
      Result[j] := c;
    End;
  SetLength(Result, j);
End;
Eigentlich der gleiche Code wie vom Grenzgaenger... Optimieren kann man das, indem man z.B. bis zum ersten Auftreten des Zeichens springt. Insbesondere der Code von Grenzgaenger wird dann schneller.

grenzgaenger 24. Dez 2007 20:30

Re: StringReplace und doppelte Zeichen
 
Wunderbar :-)

Code:
Variante Opa: 35 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante DAX: 10 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

Variante alzaimar: 9 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante Grenzgaenger: 10 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante himitsu: 10 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen
keine Ahnung wie Alzaimar das geschafft hat... denke, da kann man dann nur noch mit Assembler was rausholen... viel wirds aber nicht mehr werden...

alzaimar 24. Dez 2007 20:45

Re: StringReplace und doppelte Zeichen
 
Zitat:

Zitat von grenzgaenger
keine Ahnung wie Alzaimar das geschafft hat...

Ich habe eine Stringindizierung weniger als Du. Also ich nicht, sondern der Code. :stupid:

Versuch doch mal:

Delphi-Quellcode:
procedure ReplaceDChar(Var Quelle: string; aChar: char);
var
  i, j: integer;
  c : Char;
label
  1;

begin
  // Erstmal zum ersten Auftreten von aChar hüpfen.
  For j := 1 to Length (Quelle) Do
    if Quelle[j]=aChar then
      goto 1; // Nicht hauen, soll ja schnell sein

  Exit;
// --------
1:c := quelle[j];
  for i := j+1 to length(quelle) do
   if (quelle[i]<>c) or (aChar<>c) then
   begin
    j := j + 1;
    c := quelle[i];
    quelle[j] := c;
   end;
  setlength(quelle, j);
end;
Könnte funktionieren und könnte auch noch schneller sein.

Dann könnte man noch darauf verzichten, jedesmal ein einzelnen Zeichen zu bewegen. Erst wenn sich (j-i) ändert, kopiert man per Copy (was schneller ist, als Zeichen-für-Zeichen zu kopieren) das letzte Teilstück. Auch das könnte was bringen.

grenzgaenger 24. Dez 2007 20:58

Re: StringReplace und doppelte Zeichen
 
tja, war wohl nicht ganz so gut ... mit dem goto ...

Code:
Variante Opa: 34 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante DAX: 11 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

Variante alzaimar: 11 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante Grenzgaenger: 11 Ticks mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante himitsu: 10 Ticks mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen
2 ticks langsamer...

Dax 24. Dez 2007 21:01

Re: StringReplace und doppelte Zeichen
 
Delphi-Quellcode:
function ReduceMultiples(const s: string; c: char): string;
var
  pe, pr, pc: PChar;
  i: integer;
begin
  if s = '' then exit;
  SetLength(result, Length(s));
  pc := @s[1];
  i := 0;
  while pc^ <> c do begin
    Inc(pc);
    Inc(i);
  end;
  if i > 0 then begin
    Move(s[1], result[1], i);
    pe := @s[i+1] + Length(s) - i;
    pr := @result[i+1];
  end else begin
    pe := @s[1] + Length(s);
    pr := @result[1];
  end;
  while pc <> pe do begin
    while (pr^ = pc^) and (pc^ = c) do
      Inc(pc);
    pr^ := pc^;
    Inc(pr);
    Inc(pc);
  end;
  SetLength(result, pr - @result[1]);
end;
Gehts so?

grenzgaenger 24. Dez 2007 21:12

Re: StringReplace und doppelte Zeichen
 
Fehlermeldung:

Delphi-Quellcode:
  if i > 0 then begin
    Move(@s[1], @result[1], i); << E2036 Variable erforderlich
    pe := @s[i+1] + Length(s) - i;
    pr := @result[i+1];

Dax 24. Dez 2007 21:18

Re: StringReplace und doppelte Zeichen
 
Wurde korrigiert... Habs mit den Argumenten etwas verwirrt.

grenzgaenger 24. Dez 2007 21:33

Re: StringReplace und doppelte Zeichen
 
Fehlermeldung:

Delphi-Quellcode:
  if i > 0 then begin
    Move(s[1], result[1], i);
    pe := @s[i+1] + Length(s) - i; << E2015 Operator ist auf diesen Operantentyp nicht anwendbar

Dax 24. Dez 2007 21:37

Re: StringReplace und doppelte Zeichen
 
*lach* Wieso funktioniert es nur bei himi? Wenn ich nur Delphi hätte, das ganze auch zu testen ;)

Delphi-Quellcode:
function ReduceMultiples(const s: string; c: char): string;
var
  pe, pr, pc: PChar;
  i: integer;
begin
  if s = '' then exit;
  SetLength(result, Length(s));
  pc := @s[1];
  i := 0;
  while pc^ <> c do begin
    Inc(pc);
    Inc(i);
  end;
  if i > 0 then begin
    Move(s[1], result[1], i);
    pe := PChar(Integer(@s[i+1]) + Length(s) - i);
    pr := @result[i+1];
  end else begin
    pe := PChar(Integer(@s[1]) + Length(s));
    pr := @result[1];
  end;
  while pc <> pe do begin
    while (pr^ = pc^) and (pc^ = c) do
      Inc(pc);
    pr^ := pc^;
    Inc(pr);
    Inc(pc);
  end;
  SetLength(result, Integer(pr) - Integer(@result[1]));
end;
Wenn das jetzt nicht läuft, geb ichs aber auf.

grenzgaenger 24. Dez 2007 21:42

Re: StringReplace und doppelte Zeichen
 
fast :-)

Code:
Variante Opa: 35 Ticks (0.0097778 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante DAX: 11 Ticks (0.0030730 ms) mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xxxxCCCxxx mit Zeichen

Variante alzaimar: 10 Ticks (0.0027937 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante Grenzgaenger: 11 Ticks (0.0030730 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante himitsu: 10 Ticks (0.0027937 ms) mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

alzaimar 24. Dez 2007 21:45

Re: StringReplace und doppelte Zeichen
 
Zitat:

Zitat von grenzgaenger
tja, war wohl nicht ganz so gut ... mit dem goto ...

Kommt auf die Testdaten an. Wenn die zu eliminierenden Doubletten nicht ganz vorne stehen, bringt das schon etwas.

Da hier mal wieder Pointerarithmetik schneller zu sein scheint als Indizierung eines Strings (beim FastPos-Projekt ist es grad anders herum) habe ich meine Variante mal mit Pointern implementiert. Das wird -bei mir- doppelt so schnell. Kann eigentlich nicht sein, aber es scheint zu funktionieren... Ich erzeuge einen String der Länge 10000 mit zufälligen Zeichen aus ABCD und kürze 'A' weg.

Delphi-Quellcode:
Function RemoveCharRepetitionsP(Const aText: String; aChar: Char): String;
Var
  ip, jp, ep: PChar;
  c: Char;

Begin
  setLength(Result, Length(aText));
  If Length(aText) = 0 Then Exit;
  ip := @aText[1];
  jp := @Result[1];
  c := ip^;
  ep := ip+Length (aText);

  Result[1] := c;
  inc(ip);
  while ip<ep do begin
    If (c <> aChar) Or (ip^ <> c) Then Begin
      Inc(jp);
      c := ip^;
      jp^:=c;
    End;
    inc (ip);
    End;
  SetLength(Result, jp-@Result[1]+1);
End;

grenzgaenger 24. Dez 2007 21:53

Re: StringReplace und doppelte Zeichen
 
Das ist hier bei den Testdaten gleich schnell...

Code:
Variante Opa: 34 Ticks (0.0094984 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante DAX: 12 Ticks (0.0033524 ms) mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xxxxCCCxxx mit Zeichen

Variante alzaimar: 9 Ticks (0.0025143 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante Grenzgaenger: 12 Ticks (0.0033524 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante himitsu: 10 Ticks (0.0027937 ms) mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen
aber stimmt schon, hängt ebenfalls von den testdaten (länge, aufbau und menge) ab.

Denke, jetzt sollten wir Weihnachten feiern, Opa ist auch glücklich da seine routine um das 380% schneller geworden ist, und das ganze ohne 'ne zeile Assembler :-)

Wünsche noch frohe Weihnachten :-)

alzaimar 24. Dez 2007 21:55

Re: StringReplace und doppelte Zeichen
 
Hi Grenzgaenger. Hast Recht, Kinder sind inner Falle und nu is Ruhe im Stall.

Teste mal mit längeren Strings, da sollte der Performancegewinn schon mehr auffallen.

grenzgaenger 24. Dez 2007 21:56

Re: StringReplace und doppelte Zeichen
 
Ist auch nicht so. Dein Code mit dem Array ist schneller als der mit den Pointern

Code:
Variante Opa: 35 Ticks (0.0097778 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante DAX: 12 Ticks (0.0033524 ms) mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xxxxCCCxxx mit Zeichen

Variante alzaimar Pointer: 10 Ticks (0.0027937 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante Grenzgaenger: 12 Ticks (0.0033524 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante himitsu: 11 Ticks (0.0030730 ms) mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

Variante alzaimar Induziertes Array: 9 Ticks (0.0025143 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Hawkeye219 25. Dez 2007 10:12

Re: StringReplace und doppelte Zeichen
 
Hallo,

wenn man nicht gerade nach dem Zeichen #0 suchen möchte, dann dürfte auch folgende Routine funktionieren:

Delphi-Quellcode:
function ReduceMultipleChars (const s: string; c: Char = ' '): string;
var
  pRead, pEnd, pWrite : PChar;
begin
  pRead := PChar(s);
  pEnd := pRead + Length(s);

  SetLength (Result, Length(s));
  pWrite := PChar(Result);

  while (pRead <> pEnd) do
    begin

      repeat
        pWrite^ := pRead^;
        Inc (pRead);
        Inc (pWrite);
      until ((pRead[-1] = c) or (pRead = pEnd));

      while (pRead^ = c) do
        Inc (pRead);

    end;

  SetLength (Result, pWrite - PChar(Result));
end;
Frohe Weihnachten!

grenzgaenger 25. Dez 2007 10:24

Re: StringReplace und doppelte Zeichen
 
Respekt :-)

Delphi-Quellcode:
Variante Opa: 34 Ticks (0.0094984 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante DAX: 12 Ticks (0.0033524 ms) mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xxxxCCCxxx mit Zeichen

Variante alzaimar Pointer: 9 Ticks (0.0025143 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante Grenzgaenger: 11 Ticks (0.0030730 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante himitsu: 10 Ticks (0.0027937 ms) mit dem Ergebnis: Falsche Konvertierung
Ergebnisstring: Dies ist ein Test xCx mit Zeichen

Variante alzaimar Induziertes Array: 9 Ticks (0.0025143 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen

Variante Hawkeye219: 9 Ticks (0.0025143 ms) mit dem Ergebnis: Erfolgreich
Ergebnisstring: Dies ist ein Test xCCCx mit Zeichen
langsam darf ich da den Testrahmen noch ausbauen... um die Unterschiede herauszuextrahieren... :-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:26 Uhr.
Seite 1 von 2  1 2      

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