Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Suche StringReplace mit Widestrings (https://www.delphipraxis.net/46963-suche-stringreplace-mit-widestrings.html)

xaromz 3. Jun 2005 19:25


Suche StringReplace mit Widestrings
 
Hallo,

ich suche (wie der Titel schon sagt) eine StringReplace-Funktion mit WideStrings. In der Code-Library ist ja ein Ersatz drin, der sich leicht anpassen lässt. Drunter sind aber auch Links zu besseren Funktionen, die aber nur mit AnsiStrings funktionieren. Ich habe leider keine Zeit, mich da einzuarbeiten und das anzupassen (Ich muss mich ja ums eigentliche Projekt kümmern).
Darum meine Frage: Hat jemand eine schnelle Funktion? Ach ja, ich brauch kein case sensitive.

Gruß
xaromz

marabu 3. Jun 2005 20:27

Re: Suche StringReplace mit Widestrings
 
Hallo xaromz,

wenn du nur den Ansi-kompatiblen Subset von Unicode verwendest, dann kannst du einfach auf die Auto-Konversion von WideStrings und AnsiStrings zurück greifen und die schönen Routinen aus StrUtils weiter verwenden - oder ist das jetzt zu einfach?

Grüße vom marabu

xaromz 3. Jun 2005 20:29

Re: Suche StringReplace mit Widestrings
 
Hallo,

ich schreib grad 'ne Software, die auch in Asien verwendet werden soll. Ich brauch also wirklich WideStrings.

Gruß
xaromz

malo 3. Jun 2005 20:32

Re: Suche StringReplace mit Widestrings
 
Ich hab mal so ne Frage, aber... was stört dich, wenn man einfach den Funktionskopf entsprechend ändert?

Delphi-Quellcode:
function ConvertCharacters(aString, FromStr, ToStr: WideString): WideString;
Bei meinem Test hat es funktioniert (WideString bearbeiten). :gruebel:

xaromz 3. Jun 2005 20:34

Re: Suche StringReplace mit Widestrings
 
Hallo,

Zitat:

Zitat von malo
Ich hab mal so ne Frage, aber... was stört dich, wenn man einfach den Funktionskopf entsprechend ändert?

Hab ich ja gemacht. Was mich stört, ist dass ich Strings mit einer Länge von mehreren MB habe und deshalb möglichst schnelle Routinen brauche.

Gruß
xaromz

xaromz 6. Jun 2005 08:01

Re: Suche StringReplace mit Widestrings
 
Hallo,

sieht wohl so aus, als hätte ich doch Zeit mich damit zu beschäftigen; antworte ich mir eben selbst.

Delphi-Quellcode:
function StringReplace(const Source, OldPattern, NewPattern: WideString): WideString;
// Replace every occurrence, case insensitive
var
   C: Integer;
   FoundCount: Integer;
   SourcePosition: Integer;
   Positions: array of Integer;

   SourceLength, OldPatternLength, NewPatternLength: Integer;
   WideCharLength: Integer;
   Helper: Integer;

   PSource, PDest, PNew: PWideChar;
begin
  // Is there anything to do?
  if (OldPattern = NewPattern) or
     (Source = '') or
     (OldPattern = '') then
  begin
    Result := Source;
    Exit;
  end;

  // Initialize some variables
  SourceLength := Length(Source);
  OldPatternLength := Length(OldPattern);
  NewPatternLength := Length(NewPattern);
  WideCharLength := SizeOf(WideChar);

  FoundCount := 0;

  // We *should* range check here, but who has strings > 4GB ?
  SetLength(Positions, SourceLength div OldPatternLength + 1);

  Helper := OldPatternLength * WideCharLength;

  C := 1;
  while C <= SourceLength - OldPatternLength + 1 do
  begin
    if Source[C] = OldPattern[1] then // Check first char before we waste a jump to CompareMem
    begin
      if CompareMem(@Source[C], @OldPattern[1], Helper) then
      begin
        Positions[FoundCount] := C; // Store the found position
        Inc(FoundCount);
        Inc(C, OldPatternLength - 1); // Jump to after OldPattern
      end;
    end;
    Inc(C);
  end;

  if FoundCount > 0 then // Have we found anything?
  begin
    // We know the length of the result
    // Again, we *should* range check here...
    SetLength(Result, SourceLength + FoundCount * (NewPatternLength - OldPatternLength));

    // Initialize some variables
    SourcePosition := 1;
    PSource := PWideChar(Source);
    PDest := PWideChar(Result);
    PNew := PWideChar(NewPattern);
    Helper := NewPatternLength * WideCharLength;

    // Replace...
    for C := 0 to FoundCount - 1 do
    begin
      // Copy original and advance resultpos
      Move(PSource^, PDest^, (Positions[C] - SourcePosition) * WideCharLength);
      Inc(PDest, Positions[C] - SourcePosition);

      // Append NewPattern and advance resultpos
      Move(PNew^, PDest^, Helper);
      Inc(PDest, NewPatternLength);

      // Jump to after OldPattern
      Inc(PSource, Positions[C] - SourcePosition + OldPatternLength);
      SourcePosition := Positions[C] + OldPatternLength;
    end;
    // Append characters after last OldPattern
    Move(PSource^, PDest^, (SourceLength - SourcePosition + 1) * WideCharLength);
  end else
    Result := Source; // Nothing to replace

  // Clean up
  Finalize(Positions);
end;
Bisher schneller als alles, was ich gefunden hab. Vermutlich kann das aber jemand noch verbessern (Freiwillige vor :wink: ).

Gruß
xaromz

//Edit: Kleinen Fehler beseitigt


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:02 Uhr.

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