SearchBuf soWholeWord意外输出 [英] SearchBuf soWholeWord unexpected output

查看:152
本文介绍了SearchBuf soWholeWord意外输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用测试 StrUtils.SearchBuf 时[soWholeWord,soDown] 选项,出现一些意外的结果。

When testing StrUtils.SearchBuf with [soWholeWord,soDown] option, some unexpected results occurred.

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'不是整个字?

Why are ' Delphi' and ' Delphi ' not considered a whole word?

反向搜索怎么办? p>

What about a reverse search?

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.

我根本没有任何意义。除了功能是错误的。

I'm not making any sense of this at all. Except that the function is buggy.

XE7,XE6和XE中的结果相同。

Same results in XE7,XE6 and XE.

更新

QC127635 StrUtils.SearchBuf失败,[soWholeWord]选项

推荐答案

它看起来像是一个bug。以下是搜索的代码:

It looks like a bug to me. Here's the code that does the search:

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;

每次循环我们检查如果 soWholeWord 在选项中,然后提前到下一个单词的开头。但是,如果

Each time round the while loop we check if soWholeWord is in the options, and then advance to the start of the next word. But we only do that advancing if

Result <> @Buf[SelStart]

现在,结果是当前指针进入缓冲区,候选人是一个匹配的。所以这个测试检查我们是否正在搜索字符串的开始。

Now, Result is the current pointer into the buffer, the candidate for a match. And so this test checks whether or not we are at the start of the string being searched.

这个测试是什么意思是我们不能超越非字母数字文本第一个字的开头,如果搜索的字符串以非字母数字文本开头。

What this test means is that we cannot advance past the non-alphanumeric text to the start of the first word, if the searched string begins with non-alphanumeric text.

现在,您可以决定删除

Result <> @Buf[SelStart]

但是,如果你这样做,你会发现你不再匹配如果它位于字符串开始处。所以你会以不同的方式失败。处理这个问题的正确方法是确保如果我们在字符串的开始处, FindNextWordStart 不会提前,并且文本中有字母数字。

But if you do that you'll find that you no longer match the word if it is located right at the start of the string. So you'll just fail in a different way. The right way to deal with this would be to make sure that FindNextWordStart doesn't advance if we are at the start of the string, and the text there is alphanumeric.

我的猜测是,原作者写了这样的代码:

My guess is that the original author wrote the code like this:

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

然后,他们发现字符串开头的单词不匹配,并将代码更改为: / p>

Then they discovered that words at the start of the string would not match and changed the code to:

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

没有人测试如果字符串以非字母数字文本开头,会发生什么。

And nobody tested what happened if the string started with non-alphanumeric text.

这样的事情似乎完成了工作:

Something like this seems to get the job done:

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

这篇关于SearchBuf soWholeWord意外输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆