2014-09-16 24 views
6

Beim Testen der Option mit der Option [soWholeWord,soDown] sind einige unerwartete Ergebnisse aufgetreten.SearchBuf soWholeWord unerwarteter Ausgang

program Project1; 

Uses 
    SysUtils,StrUtils; 

function WordFound(aString,searchString: String): Boolean; 
begin 
    Result := SearchBuf(PChar(aString),Length(aString), 0, 0, searchString, 
    [soWholeWord,soDown]) <> nil; 
end; 

Procedure Test(aString,searchString: String); 
begin 
    WriteLn('"',searchString,'" in "',aString,'"',#9,' : ', 
    WordFound(aString,searchString)); 
end; 

begin 
    Test('Delphi','Delphi'); // True 
    Test('Delphi ','Delphi'); // True 
    Test(' Delphi','Delphi'); // False 
    Test(' Delphi ','Delphi'); // False 
    ReadLn; 
end. 

Warum sind ' Delphi' und ' Delphi ' nicht ein ganzes Wort in Betracht gezogen?

Wie wäre es mit einer Rückwärtssuche?

function WordFoundRev(aString,searchString: String): Boolean; 
begin 
    Result := SearchBuf(PChar(aString),Length(aString),Length(aString)-1,0,searchString, 
    [soWholeWord]) <> nil; 
end; 

Procedure TestRev(aString,searchString: String); 
begin 
    WriteLn('"',searchString,'" in "',aString,'"',#9,' : ', 
    WordFoundRev(aString,searchString)); 
end; 

begin 
    TestRev('Delphi','Delphi'); // False 
    TestRev('Delphi ','Delphi'); // True 
    TestRev(' Delphi','Delphi'); // False 
    TestRev(' Delphi ','Delphi'); // True 
    ReadLn; 
end. 

Ich mache überhaupt keinen Sinn davon. Nur dass die Funktion fehlerhaft ist.

Gleiche Ergebnisse in XE7, XE6 und XE.


aktualisieren

QC127635 StrUtils.SearchBuf fails with [soWholeWord] option

+1

gibt es verschiedene Fehler in der QC zum Beispiel erwähnt [Bericht Nr .: 122357] (http://qc.embarcadero.com/wc/qcmain.aspx?d = 122357) – bummi

+1

@bummi, ja ich habe die QC durchsucht und keine Übereinstimmung für dieses Vorkommen gefunden. –

Antwort

4

Es sieht aus wie ein Bug zu mir. Hier ist der Code, der die Suche tut:

while SearchCount > 0 do 
begin 
    if (soWholeWord in Options) and (Result <> @Buf[SelStart]) then 
    if not FindNextWordStart(Result) then Break; 
    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 
     ((Byte(Result[I])) in WordDelimiters) then 
     Exit; 
     Break; 
    end; 
    end; 
    Inc(Result, Direction); 
    Dec(SearchCount); 
end; 

Jedes Mal, um die while Schleife überprüfen wir, ob soWholeWord in den Optionen ist, und dann an den Anfang des nächsten Wortes vorantreiben. Aber wir haben nur das Vorschieben wenn

Result <> @Buf[SelStart] 

Nun Result der aktuellen Zeiger in den Puffer ist, der Kandidat für ein Spiel. Und so prüft dieser Test, ob wir am Anfang der gesuchten Zeichenfolge stehen oder nicht.

Dieser Test bedeutet, dass wir nicht über den nicht alphanumerischen Text hinaus zum Anfang des ersten Wortes springen können, wenn die gesuchte Zeichenfolge mit nicht-alphanumerischem Text beginnt.

Jetzt könnten Sie sich entscheiden, den Test für

Result <> @Buf[SelStart] 

zu entfernen, aber wenn Sie das tun, werden Sie feststellen, dass Sie nicht mehr das Wort übereinstimmen, wenn es gleich zu Beginn der Zeichenfolge befindet. Du versagst es einfach anders. Der richtige Weg, um damit umzugehen, wäre sicherzustellen, dass nicht vorrückt, wenn wir am Anfang des Strings stehen, und der Text dort alphanumerisch ist. sie entdeckten, dass Worte zu Beginn der Zeichenfolge nicht und

if (soWholeWord in Options) then 
    if not FindNextWordStart(Result) then Break; 

Dann, um den Code geändert würde passen:

if (soWholeWord in Options) and (Result <> @Buf[SelStart]) then 
    if not FindNextWordStart(Result) then Break; 
schrieb

Meine Vermutung ist, dass der ursprüngliche Autor den Code wie folgt

Und niemand hat getestet, was passiert ist, wenn die Zeichenfolge mit nicht-alphanumerischem Text gestartet wurde.

Etwas Ähnliches scheint die Aufgabe zu erledigen:

if (soWholeWord in Options) then 
    if (Result <> @Buf[SelStart]) or not Result^.IsLetterOrDigit then 
    if not FindNextWordStart(Result) then Break; 
+2

'Und niemand hat getestet, was passiert ist, wenn die Zeichenfolge mit nicht-alphanumerischem Text begonnen hat '. Seufz, so viele Jahre und niemand hat das vorher gefunden. Der Test ist trivial und ich frage mich, ob der RTL von Emba überhaupt getestet wird. Danke, ich werde später eine QC einreichen. –

+2

Hmm. Lass mich nicht anfangen !! –

+0

@DavidHeffernan Ich habe den ursprünglichen Code mit Ihrem Vorschlagscode ersetzt und funktioniert immer noch nicht, das betreffende Beispiel gibt die gleichen Ergebnisse zurück. Delphi 10.1 oder 10.2. –