2014-09-16 4 views
6

При тестировании StrUtils.SearchBuf с опцией [soWholeWord,soDown] произошли некоторые неожиданные результаты.SearchBuf soWholeWord неожиданный выход

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. 

Почему ' Delphi' и ' Delphi ' не считается целым словом?

А как насчет обратного поиска?

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. 

Я вообще не чувствую этого. За исключением того, что функция глючит.

Те же результаты в XE7, XE6 и XE.


Update

QC127635 StrUtils.SearchBuf fails with [soWholeWord] option

+1

есть различные ошибки, упомянутые в КК, например, [Report #: 122357] (http://qc.embarcadero.com/wc/qcmain.aspx?d = 122357) – bummi

+1

@ bummi, да, я искал QC и не нашел соответствия для этого события. –

ответ

4

Это выглядит как ошибка для меня. Вот код, который делает запрос:

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; 

Каждый раз вокруг петли while мы проверяем, если soWholeWord в меню, а затем перейти к началу следующего слова. Но мы только делаем, что опережение если

Result <> @Buf[SelStart] 

Теперь Result является текущий указатель в буфер, кандидат на матч. И поэтому этот тест проверяет, находимся ли мы в начале поиска строки.

Этот тест означает, что мы не сможем продвигаться вперед от не алфавитно-цифрового текста до начала первого слова, если искомая строка начинается с не-буквенно-цифрового текста.

Теперь вы можете решить, чтобы удалить тест на

Result <> @Buf[SelStart] 

Но если вы делаете, что вы обнаружите, что вы больше не совпадают слово, если оно расположено в самом начале строки. Таким образом, вы просто потерпите неудачу по-другому. Правильный способ справиться с этим - убедиться, что FindNextWordStart не продвигается, если мы находимся в начале строки, а текст - буквенно-цифровой.

Я думаю, что автор написал такой код:

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

Затем они обнаружили, что слова в начале строки не будет соответствовать и изменил код:

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

И никто не проверял, что произошло, если строка началась с не-буквенно-цифрового текста.

Нечто подобное, кажется, чтобы получить работу:

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

'И никто не проверял, что произошло, если строка начиналась с не-буквенно-цифрового текста'. Вздох, так много лет, и никто раньше этого не нашел. Тест тривиален, и это заставляет меня задаться вопросом, тестируется ли RTL модулем Emba вообще. Спасибо, позже я отправлю QC. –

+2

Хм. Не заводи меня! –

+0

@DavidHeffernan Я заменил исходный код кодом предложения и до сих пор не работает, пример, о котором идет речь, возвращает те же результаты. Delphi 10.1 или 10.2. –

Смежные вопросы