델파이에 효율적인 전체 단어 검색 기능이 있습니까?
문제
Delphi 2009 이후 (유니 코드)에는 단어를 정의하는 구분자를 제공하는 합리적으로 효율적인 전체 단어 검색을 수행 할 내장 기능 또는 작은 루틴이 있습니까?
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 루틴은 내가 필요한 것입니다. 스트 루틸 루틴에 들어가서 코드를 추출하여 요구 사항에 맞게 수정할 수도 있습니다.
SearchBuf가 먼저 단어를 검색 한 다음 구분자를 확인하지 않는다는 사실에 놀랐습니다. 대신, 그것은 구분기를 찾기 위해 한 번에 하나씩 문자열의 문자를 통과합니다. 하나를 찾으면 문자열과 다른 구분기를 확인합니다. 그것을 찾지 못하면 다른 구분 기호를 찾습니다. 효율성을 위해서는 매우 똑똑합니다!
해결책
당신은 사용할 수 있습니다 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의 편집기가 "Word Match"기능을 가지고 있다고해서 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;