Announcement

Collapse
No announcement yet.

StringReplace nur für ganze Wörter?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • StringReplace nur für ganze Wörter?

    Hallo,

    gibt es eine Funktion, die wie StringReplace arbeitet, aber dabei nur ganze Wörter berücksichtigt?

    Beispiel: #1 ersetzen durch Test1 betrifft auch #11, das soll aber nicht sein.

    Gruß Uli

  • #2
    Hallo,

    Borland hat vor einiger Zeit in CodeCentral eine Unit veröffentlicht, aus der diese Funktion stammt: "<i>Given a long string, replace one substring with another. Take the string: "Football Delight". The job is to replace the word Delight with Night: S := ReplaceString('Night', 'Delight', 'Football</i>":
    <pre>
    function ReplaceAllInstancesOfString(NewStr, ReplaceStr: string;
    var Data: string): Boolean;
    var
    i: Integer;
    begin
    i := 0;
    while Pos(ReplaceStr, Data) > 0 do begin
    Data := ReplaceString(NewStr, ReplaceStr, Data);
    Inc(i);
    end;
    Result := i > 0;
    end;

    function ReplaceString(NewStr, ReplaceStr, Data: string): string;
    var
    OffSet: Integer;
    begin
    OffSet := Pos(ReplaceStr, Data);
    Delete(Data, OffSet, Length(ReplaceStr));
    Insert(NewStr, Data, OffSet);
    Result := Data;
    end;
    </pre&gt

    Comment


    • #3
      Hi Uli,

      1)
      Eine fertige Funktion gibt es meines Wissens nicht.

      2)
      Du kannst deinen Suchausdruck aber in Leerzeichen einschliessen z.B. ' Suchmich '. Um auch Satzzeichen ( bzw. Sonderzeichen im allgemeinen ) zu berücksichtigen musst Du den Suchausdruck entsprechen manipulieren z.B. ' Suchausdruck.' und StringReplace mehrfach aufrufen.

      3)
      Du kannst auch erst die Position des Suchausdruckes bestimmen und dann das folgende und vorstehenden Zeichen analysieren. Ist eines davon ein Buchstabe oder eine Zahl, dann hast du einen Teilstring erwischt. Sind beide andere Zeichen, dann ist es ein ganzes Wort. In letzterem Fall erweiterst du deinen Suchausdruck wieder um die begrenzenden Zeichen der Fundstelle und rufst Stringreplace auf.

      Gruß
      Gesin

      Comment


      • #4
        Hallo Gesine,

        danke für Deine Hilfe.

        Mit 2) hatte ich es bereits realisiert, schien mir aber ziemlich umständlich zu sein, 3) schaut eleganter aus. 1) :-((

        Herzliche Grüße Ul

        Comment


        • #5
          Hallo Uli,<br>
          <br>
          wenn sich der Text in einem RichEdit befindet, kannst Du die Methode FindText verwenden.<br>
          Der kannst Du die Optionen stWholeWord, bzw. stMatchCase mitgeben.<br>
          Wenn der Text gefunden wurde kann das Ergebnis von FindText als SelStart gesetzt werden, und SelLength wird mit der Länge des Suchtextes versorgt.<br>
          Mit SetSelTextBuf kannst Du dann den Text ersetzen.<br>
          Eingeschränkt wird das ganze allerdings dadurch, das die Begrenzungen für stWholeWord festliegen,<br>
          und nicht angegeben werden können.<br>
          Für den Fall ist die laufende Nummer 2 von Gesine wohl sehr viel besser geeignet, da sie auch flexibler ist.<br>
          <br>
          Ciao<br>
          Chri

          Comment


          • #6
            Genauer gesagt müsste auch das Komma, Fragezeichen, Leerzeichen, Punkt, Semikolon, Ausrufezeichen, Doppelpunkt als Trennzeichen benutzt werden. Damit fällt Gesines Fall No 2.) wohl ins Wassser, da ja anstatt der Leerzeichen JEDES andere Trennzeichen gültig wäre.

            <pre>

            function CountWords(const S: String): Integer;

            var
            P: PChar;
            LastWord: PChar;
            begin
            P := PChar(S);
            Result := 0;
            LastWord := nil;
            while P^ <> #0 do
            begin
            // Zeichenset wie in Pascal Source
            if not P^ in ['a'..'z', 'A'..'Z', '0'..'9', '_'] then
            begin
            if LastWord <> nil then
            begin
            Inc(Result); // Word-counter

            // hier kann LastWord ausgewertet werden.
            // P - LastWord - 1 ist die Länge des Wortes.

            LastWord := nil;
            end;
            end else
            if LastWord = nil then LastWord := P;
            Inc(P);
            end;
            end;

            </pre>

            obiger Code ist ein Ansatzpunkt.

            Gruß Hage

            Comment


            • #7
              Hallo Uli,<br>
              <br>
              wenn sich der Text in einem RichEdit befindet, kannst Du die Methode FindText verwenden.<br>
              Der kannst Du die Optionen stWholeWord, bzw. stMatchCase mitgeben.<br>
              Wenn der Text gefunden wurde kann das Ergebnis von FindText als SelStart gesetzt werden, und SelLength wird mit der Länge des Suchtextes versorgt.<br>
              Mit SetSelTextBuf kannst Du dann den Text ersetzen.<br>
              Eingeschränkt wird das ganze allerdings dadurch, das die Begrenzungen für stWholeWord festliegen,<br>
              und nicht angegeben werden können.<br>
              <br>
              Ciao<br>
              Chri

              Comment


              • #8
                @Hagen: Klar hast Du Recht, Dein Code sieht sehr interessant aus; werde mich damit beschäftigen.

                Danke!

                @Christian: Leider kein RTF.

                Gruß Ul

                Comment


                • #9
                  Hallo, in Delphi 6 gibt es eine fertige Funktion.
                  Vielleicht hilft die?

                  Gruß
                  Reinhold

                  <pre>

                  { SearchBuf is a search routine for arbitrary text buffers. If a match is
                  found, the function returns a pointer to the start of the matching
                  string in the buffer. If no match, the function returns nil. Specify
                  soDown to search forward otherwise the search is performs
                  backwards through the text. Use SelStart and SelLength skip "selected"
                  text thus the search will start before or after (soDown) the specified text. }

                  function TMrsFileSearch.SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TMrsStringSearchOptions): PChar;
                  var
                  SearchCount, I: Integer;
                  C: Char;
                  Direction: Shortint;
                  CharMap: array [Char] of Char;
                  {----------------------------------------------------------------------------}
                  function FindNextWordStart(var BufPtr: PChar): Boolean;
                  begin { (True XOR N) is equivalent to (not N) }
                  { (False XOR N) is equivalent to (N) }
                  { When Direction is forward (1), skip non delimiters, then skip delimiters. }
                  { When Direction is backward (-1), skip delims, then skip non delims }
                  while (SearchCount > 0) and ((Direction = 1) xor (BufPtr^ in WordDelimiters)) do begin
                  Inc(BufPtr, Direction);
                  Dec(SearchCount);
                  end;
                  while (SearchCount > 0) and ((Direction = -1) xor (BufPtr^ in WordDelimiters)) do begin
                  Inc(BufPtr, Direction);
                  Dec(SearchCount);
                  end;
                  Result := SearchCount > 0;
                  if Direction = -1 then begin { back up one char, to leave ptr on first non delim }
                  Dec(BufPtr, Direction);
                  Inc(SearchCount);
                  end;
                  end;
                  {----------------------------------------------------------------------------}
                  begin
                  Result := nil;
                  if BufLen <= 0 then Exit;
                  if soDown in Options then
                  begin
                  Direction := 1;
                  Inc(SelStart, SelLength); { start search past end of selection }
                  SearchCount := BufLen - SelStart - Length(SearchString) + 1;
                  if SearchCount < 0 then Exit;
                  if Longint(SelStart) + SearchCount > BufLen then Exit;
                  end
                  else begin
                  Direction := -1;
                  Dec(SelStart, Length(SearchString));
                  SearchCount := SelStart + 1;
                  end;
                  if (SelStart < 0) or (SelStart > BufLen) then Exit;
                  Result := @Buf[SelStart];
                  { Using a Char map array is faster than calling AnsiUpper on every character }
                  for C := Low(CharMap) to High(CharMap) do CharMap[C] := C;
                  if not (soMatchCase in Options) then begin
                  AnsiUpperBuff(PChar(@CharMap), sizeof(CharMap));
                  AnsiUpperBuff(@SearchString[1], Length(SearchString));
                  end;
                  while SearchCount > 0 do begin
                  if (soWholeWord in Options) and (Result <> @Buf[SelStart]) then begin
                  if not FindNextWordStart(Result) then Break;
                  end;
                  I := 0;
                  while (CharMap[Result[I]] = SearchString[I+1]) do begin
                  Inc(I);
                  if I >= Length(SearchString) then begin
                  if (not (soWholeWord in Options)) or (SearchCount = 0) or (Result[I] in WordDelimiters) then Exit;
                  Break;
                  end;
                  end;
                  Inc(Result, Direction);
                  Dec(SearchCount);
                  end;
                  Result := nil;
                  end;

                  </pre&gt

                  Comment


                  • #10
                    Hallo, in Delphi 6 gibt es eine fertige Funktion.
                    Vielleicht hilft die?

                    Gruß
                    Reinhold

                    <pre>

                    { SearchBuf is a search routine for arbitrary text buffers. If a match is
                    found, the function returns a pointer to the start of the matching
                    string in the buffer. If no match, the function returns nil. Specify
                    soDown to search forward otherwise the search is performs
                    backwards through the text. Use SelStart and SelLength skip "selected"
                    text thus the search will start before or after (soDown) the specified text. }

                    function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TMrsStringSearchOptions): PChar;
                    var
                    SearchCount, I: Integer;
                    C: Char;
                    Direction: Shortint;
                    CharMap: array [Char] of Char;
                    {----------------------------------------------------------------------------}
                    function FindNextWordStart(var BufPtr: PChar): Boolean;
                    begin { (True XOR N) is equivalent to (not N) }
                    { (False XOR N) is equivalent to (N) }
                    { When Direction is forward (1), skip non delimiters, then skip delimiters. }
                    { When Direction is backward (-1), skip delims, then skip non delims }
                    while (SearchCount > 0) and ((Direction = 1) xor (BufPtr^ in WordDelimiters)) do begin
                    Inc(BufPtr, Direction);
                    Dec(SearchCount);
                    end;
                    while (SearchCount > 0) and ((Direction = -1) xor (BufPtr^ in WordDelimiters)) do begin
                    Inc(BufPtr, Direction);
                    Dec(SearchCount);
                    end;
                    Result := SearchCount > 0;
                    if Direction = -1 then begin { back up one char, to leave ptr on first non delim }
                    Dec(BufPtr, Direction);
                    Inc(SearchCount);
                    end;
                    end;
                    {----------------------------------------------------------------------------}
                    begin
                    Result := nil;
                    if BufLen <= 0 then Exit;
                    if soDown in Options then
                    begin
                    Direction := 1;
                    Inc(SelStart, SelLength); { start search past end of selection }
                    SearchCount := BufLen - SelStart - Length(SearchString) + 1;
                    if SearchCount < 0 then Exit;
                    if Longint(SelStart) + SearchCount > BufLen then Exit;
                    end
                    else begin
                    Direction := -1;
                    Dec(SelStart, Length(SearchString));
                    SearchCount := SelStart + 1;
                    end;
                    if (SelStart < 0) or (SelStart > BufLen) then Exit;
                    Result := @Buf[SelStart];
                    { Using a Char map array is faster than calling AnsiUpper on every character }
                    for C := Low(CharMap) to High(CharMap) do CharMap[C] := C;
                    if not (soMatchCase in Options) then begin
                    AnsiUpperBuff(PChar(@CharMap), sizeof(CharMap));
                    AnsiUpperBuff(@SearchString[1], Length(SearchString));
                    end;
                    while SearchCount > 0 do begin
                    if (soWholeWord in Options) and (Result <> @Buf[SelStart]) then begin
                    if not FindNextWordStart(Result) then Break;
                    end;
                    I := 0;
                    while (CharMap[Result[I]] = SearchString[I+1]) do begin
                    Inc(I);
                    if I >= Length(SearchString) then begin
                    if (not (soWholeWord in Options)) or (SearchCount = 0) or (Result[I] in WordDelimiters) then Exit;
                    Break;
                    end;
                    end;
                    Inc(Result, Direction);
                    Dec(SearchCount);
                    end;
                    Result := nil;
                    end;

                    </pre&gt

                    Comment

                    Working...
                    X