2009-11-05 59 views
5

德尔福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 } 

我只需要这个返回一个true或false值,如果“道”是的字符串中。

因为标准的查找对话框具有“仅匹配整个单词”作为它的一个选项,所以在某处应该有一些东西。

这是如何实现的(或最好的)?


结论:

RRUZ的答案是完美的。 SearchBuf例程正是我所需要的。我甚至可以进入StrUtils例程,提取代码并对其进行修改以符合我的要求。

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

回答

13

您可以使用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]); 

再见。

+1

不错!您现在将自己的解决方案发布在您自己的博客上,网址为:http://theroadtodelphi.wordpress.com/2009/11/05,因为我做了进一步的调查。感谢您提供的额外信息。 – lkessler 2009-11-06 04:54:48

+0

'ExistWordInString('Delphi','Delphi'[soWholeWord,soDown]);'失败。查看[SearchBuf soWholeWord意外输出](http://stackoverflow.com/q/25877986/576719)。 – 2014-09-16 21:12:35

2

仅仅因为Delphi的编辑器有一个“字匹配”功能,这并不意味着Delphi库提供它!

通常情况下,在大多数语言中,这样做的方式是正则表达式。看起来它们(仍然)没有内置在Delphi中,因为有第三方库提供了该功能。我找到的第一个例子是:http://delphi.about.com/od/toppicks/tp/delphi-regular-expressions.htm

通常情况下,你会建立一个正则表达式像

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

你想从你的库的文档获取详细信息。我的例子没有正确处理从Str开头或结尾开始的单词,或者是Str的全部。

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; 
0

如果你有功能类似下面

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]); 

如果你一次调用它,你可能不会遇到任何问题。但是,如果你使用Pos函数(如下图)首先使用Pos函数(例如1000次或更多)来调用此函数将令人惊讶地给你额外的性能

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;