AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Library: Object-Pascal / Delphi-Language Delphi Mehrere Strings auf einmal ersetzen
Thema durchsuchen
Ansicht
Themen-Optionen

Mehrere Strings auf einmal ersetzen

Ein Thema von Matze · begonnen am 22. Apr 2006 · letzter Beitrag vom 26. Apr 2006
 
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.929 Beiträge
 
Turbo Delphi für Win32
 
#1

Mehrere Strings auf einmal ersetzen

  Alt 22. Apr 2006, 19:21
xaromz hat hier eine Routine gepostet, die es ermöglicht, mehrere Strings auf einmal zu ersetzen, somit entfält der mehrmalige Aufruf von Delphi-Referenz durchsuchenStringReplace.

Die Parameter sind eigentlich selbsterklärend.

Delphi-Quellcode:
uses
  SysUtils;

...

function StringReplaceMultiple(const Source: AnsiString;
  const OldPatterns, NewPatterns: array of AnsiString;
  CaseSensitive: Boolean = True): AnsiString;
// Replace every occurrence

type
  TFoundPos = record
    Position: Integer;
    PatternNum: Integer;
  end;

var
  C: Integer;
  FoundCount: Integer;
  SourcePosition: Integer;
  PatternCount: Integer;
  Positions: array of TFoundPos;
  PositionLength: Integer;

  PatternNum: Integer;
  SourceLength, OldPatternLength, NewPatternLength: Integer;
  OldLengths, NewLengths: array of Integer;
  DeltaOld: Integer;

  Delta: Integer;

  PSource, PDest, PNew: PAnsiChar;

  SearchSource: AnsiString;
  CasePatterns: array of AnsiString;

  I: Integer;
begin
  if (Source = '') or (Length(OldPatterns) <> Length(NewPatterns)) then
  begin
    Result := Source;
    Exit;
  end;

  try
    // Initialize some variables
    PatternCount := Length(OldPatterns);
    SourceLength := Length(Source);
    SetLength(OldLengths, PatternCount);
    SetLength(NewLengths, PatternCount);
    Delta := 0;
    DeltaOld := 0;
    for C := 0 to PatternCount - 1 do
    begin
      OldLengths[C] := Length(OldPatterns[C]);
      NewLengths[C] := Length(NewPatterns[C]);
      Inc(DeltaOld, OldLengths[C]);
    end;
    DeltaOld := Round(DeltaOld / PatternCount);

    SetLength(CasePatterns, PatternCount);
    if CaseSensitive then
    begin
      SearchSource := Source;
      for C := 0 to PatternCount - 1 do
        CasePatterns[C] := OldPatterns[C];
    end else
    begin
      SearchSource := AnsiLowerCase(Source);
      for C := 0 to PatternCount - 1 do
        CasePatterns[C] := AnsiLowerCase(OldPatterns[C]);
    end;

    FoundCount := 0;

    // ----------------------------------
    // Check the amount of replaces
    // ----------------------------------

    // We *should* range check here, but who has strings > 2GB ?
    PositionLength := SourceLength div DeltaOld + 1;
    SetLength(Positions, PositionLength);

    C := 1;
    while C <= SourceLength do
    begin
      for PatternNum := 0 to PatternCount - 1 do
      begin
        if (SearchSource[C]) = (CasePatterns[PatternNum][1]) then // Check first char before we waste a jump to CompareMem
        begin
          if CompareMem(@SearchSource[C], @CasePatterns[PatternNum][1], OldLengths[PatternNum]) then
          begin
            if FoundCount >= PositionLength then
            begin
              Inc(PositionLength, 4);
              SetLength(Positions, PositionLength);
            end;

            Positions[FoundCount].Position := C; // Store the found position
            Positions[FoundCount].PatternNum := PatternNum;
            Inc(FoundCount);
            Inc(C, OldLengths[PatternNum] - 1); // Jump to after OldPattern
            Inc(Delta, NewLengths[PatternNum] - OldLengths[PatternNum]);
            Break;
          end;
        end;
      end;
      Inc(C);
    end;

    SetLength(CasePatterns, 0);

    // ----------------------------------
    // Actual replace
    // ----------------------------------

    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 + Delta);

      // Initialize some variables
      SourcePosition := 1;
      PSource := PAnsiChar(Source);
      PDest := PAnsiChar(Result);

      // Replace...

      for C := 0 to FoundCount - 1 do
      begin
        // Copy original and advance resultpos
        PNew := PAnsiChar(NewPatterns[Positions[C].PatternNum]);

        Move(PSource^, PDest^, Positions[C].Position - SourcePosition);
        Inc(PDest, Positions[C].Position - SourcePosition);

        // Append NewPattern and advance resultpos
        Move(PNew^, PDest^, NewLengths[Positions[C].PatternNum]);
        Inc(PDest, NewLengths[Positions[C].PatternNum]);

        // Jump to after OldPattern
        Inc(PSource, Positions[C].Position - SourcePosition + OldLengths[Positions[C].PatternNum]);
        SourcePosition := Positions[C].Position + OldLengths[Positions[C].PatternNum];
      end;

      // Append characters after last OldPattern
      Move(PSource^, PDest^, SourceLength - SourcePosition + 1);
    end else
      Result := Source; // Nothing to replace

    // Clean up
    Finalize(Positions);
  except
  end;
end;
Der Code würde als praktische Ergänzung zu diesem Code dienen.
  Mit Zitat antworten Zitat
 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:24 Uhr.
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