7

在 Delphi 2009 或更高版本 (Unicode) 中,是否有任何内置函数或小例程编写在某处可以进行相当有效的全词搜索,您可以在其中提供定义单词的分隔符,例如:

function ContainsWord(Word, Str: string): boolean;

const  { Delim holds the delimiters that are on either side of the word }
  Delim = ' .;,:(){}"/\<>!?[]'#$91#$92#$93#$94'-+*='#$A0#$84;

在哪里:

Word: string;  { is the Unicode string to search for }
Str: string;   { is the Unicode string to be searched }

如果“Word”在字符串中,我只需要它来返回真值或假值。

某处必须有一些东西,因为标准的“查找”对话框将“仅匹配整个单词”作为其选项之一。

这通常(或最好)如何实施?


结论:

RRUZ 的回答很完美。SearchBuf 例程正是我所需要的。我什至可以进入 StrUtils 例程,提取代码并对其进行修改以满足我的要求。

我惊讶地发现 SearchBuf 不会先搜索单词然后再检查分隔符。相反,它一次一个地遍历字符串的字符来寻找分隔符。如果找到,则检查字符串和另一个分隔符。如果它没有找到它,它会寻找另一个分隔符。为了效率,这很聪明!

4

4 回答 4

19

您可以将SearchBuf函数与 [soWholeWord] 选项一起使用。

function SearchBuf(Buf: PAnsiChar; BufLen: Integer; SelStart: Integer; SelLength: Integer; SearchString: AnsiString; Options: TStringSearchOptions): PAnsiChar;

看这个例子

function ExistWordInString(aString:PWideChar;aSearchString:string;aSearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
Begin
      Size:=StrLen(aString);
      Result := SearchBuf(aString, Size, 0, 0, aSearchString, aSearchOptions)<>nil;
End;

以这种方式使用它

ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);

再见。

于 2009-11-05T07:05:44.797 回答
2

仅仅因为 Delphi 的编辑器具有“单词匹配”功能,并不意味着 Delphi 库提供了它!

通常,在大多数语言中,这样做的方法是使用正则表达式。似乎它们(仍然)没有内置到 Delphi 中,因为有 3rd 方库提供了该功能。我发现的第一个例子是:http ://delphi.about.com/od/toppicks/tp/delphi-regular-expressions.htm 。

通常,您会构建一个正则表达式,例如

myRegex = '[' + Delim + ']+' + Word + '[' + Delim + ']+';
if regexSearch (Str, myRegex) then ...

您将希望从您获得的库的文档中获取详细信息。我的示例没有正确处理单词从 Str 的开头开始或在其结尾结束或全部为 Str 的情况。

于 2009-11-05T06:18:13.207 回答
1

如果你有如下功能

function ExistWordInString(aString:PWideChar;aSearchString:string;aSearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
Begin
      Size:=StrLen(aString);
      Result := SearchBuf(aString, Size, 0, 0, aSearchString, aSearchOptions)<>nil;
End;

并这样称呼它:

ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);

如果你调用一次,你可能不会遇到任何问题。但是如果你在一个循环中调用它(例如 1000 次或更多)首先使用 Pos 函数(如下所示)会给你带来额外的性能

function ExistWordInString(const AString:string;const ASearchString:string;ASearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
  AWChar: PWideChar;
begin
   if Pos(LowerCase(ASearchString), LowerCase(AString)) = 0 then
   begin
      Exit(False);
   end;

   AWChar := PWideChar(AString);
   Size:=StrLen(AWChar);
   Result := SearchBuf(AWChar, Size, 0, 0, ASearchString, ASearchOptions)<>nil;
end;
于 2018-01-10T12:31:51.933 回答
0

此功能不完全是您所需要的,但它非常接近:

我希望它有用:

{ Copy all whole words from MainStr. The result will not have more than MaxChars characters. }

function CopyWords(MainStr: string; MaxChars: Integer): string;   
VAR EndsInSpace: Boolean;
    EndString, i: Integer;
    NextChar: char;
begin
 Assert(MaxChars > 0);
 EndString:= MaxChars;

 if Length(MainStr) > MaxChars then
  begin
   NextChar:= mainstr[MaxChars+1];

   if (MainStr[MaxChars] <> ' ') AND (NextChar <> ' ')
   then
     begin
      for i:= MaxChars downto 1 DO
       if MainStr[i]= ' ' then
        begin
         EndString:= i;
         Break;
        end
     end
   else
    if (MainStr[MaxChars]  = ' ')
    OR (MainStr[MaxChars] <> ' ') AND (NextChar = ' ')
    then EndString:= MaxChars;
  end;

 Result:= CopyTo(MainStr, 1, EndString);
 Result:= TrimRight(Result);
end;
于 2016-09-09T09:36:10.400 回答