Существует ли эффективная функция поиска по всему слову в Delphi?
Вопрос
В 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 }
Мне это нужно только для того, чтобы вернуть значение true или false, если "Слово" находится в строке.
Где-то должно быть что-то для этого, потому что в стандартном диалоговом окне поиска есть "Сопоставлять только целое слово" в качестве одного из вариантов.
Как это обычно (или лучше всего) реализуется?
Заключение:
Ответ РУЗ был идеальным.Процедура SearchBuf была как раз тем, что мне было нужно.Я даже могу зайти в процедуру StrUtils, извлечь код и изменить его в соответствии с моими требованиями.
Я был удивлен, обнаружив, что 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]);
Пока.
Другие советы
Просто потому, что редактор 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.
Эта функция не совсем то, что вам нужно, но она довольно близка к этому:
Я надеюсь, что это полезно:
{ 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;
Если у вас есть функция, подобная приведенной ниже
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;