delphi – SearchBuf soWholeWord意外输出
使用[soWholeWord,soDown]选项测试
StrUtils.SearchBuf时,会发生一些意外结果.
program Project1; Uses SysUtils,StrUtils; function WordFound(aString,searchString: String): Boolean; begin Result := SearchBuf(PChar(aString),Length(aString),searchString,[soWholeWord,soDown]) <> nil; end; Procedure Test(aString,searchString: String); begin WriteLn('"','" 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,Length(aString)-1,[soWholeWord]) <> nil; end; Procedure TestRev(aString,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中的结果相同. 更新 QC127635 StrUtils.SearchBuf fails with [soWholeWord] option 解决方法
对我来说这看起来像个错误.这是搜索的代码:
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; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |