2009-11-05 5 views
5

Dans Delphi 2009 ou version ultérieure (Unicode), sont-il des fonctions intégrées ou petites routines écrites quelque part qui va faire un mot entier raisonnablement efficace de recherche où vous fournissez les délimiteurs qui définissent le mot, par exemple:Existe-t-il une fonction efficace de recherche de mots entiers dans Delphi?

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; 

où:

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

Je ne besoin de ceci pour retourner une valeur true ou false si le « mot » est dans la chaîne.

Il doit y avoir quelque chose pour quelque part, parce que la boîte de dialogue de recherche standard a "Match mot entier seulement" comme une de ses options.

Comment est-ce normalement (ou le mieux) mis en œuvre?


Conclusion:

réponse de RRUZ était parfait. La routine SearchBuf était exactement ce dont j'avais besoin. Je peux même aller dans la routine StrUtils, extraire le code, et le modifier pour répondre à mes besoins.

J'ai été surpris de constater que SearchBuf ne cherche pas d'abord le mot, puis vérifie les délimiteurs. Au lieu de cela, il passe par les caractères de la chaîne un à la fois à la recherche d'un délimiteur. S'il en trouve un, il vérifie la chaîne et un autre délimiteur. S'il ne le trouve pas, il cherche alors un autre délimiteur. Par souci d'efficacité, c'est très intelligent!

Répondre

13

Vous pouvez utiliser la fonction SearchBuf avec l'option [soWholeWord].

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

Voir cet exemple

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; 

Utilisez cette façon

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

Bye.

+1

Nice! Vous avez maintenant posté votre solution sur votre propre blog à l'adresse: http://theroadtodelphi.wordpress.com/2009/11/05 et je l'ai trouvé juste après avoir fait d'autres recherches. Merci pour les informations supplémentaires que vous fournissez ici. – lkessler

+0

'ExistWordInString ('Delphi', 'Delphi' [soWholeWord, soDown])' échoue. Voir [SearchBuf soWholeWord sortie inattendue] (http://stackoverflow.com/q/25877986/576719). –

2

Ce n'est pas parce que l'éditeur de Delphi a une fonction de «correspondance de mots» que la bibliothèque Delphi l'offre!

Typiquement, dans la plupart des langues, la façon de procéder est une expression régulière. Il semble qu'ils ne soient pas (encore) intégrés à Delphi, car il existe des bibliothèques tierces offrant cette fonctionnalité. Le premier exemple que j'ai trouvé est: http://delphi.about.com/od/toppicks/tp/delphi-regular-expressions.htm.

En règle générale, vous souhaitez construire une chose régulière d'expression comme

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

Vous voulez obtenir des détails de la documentation de la bibliothèque que vous obtenez. Mon exemple ne gère pas correctement le cas du mot commençant au début de Str ou finissant à sa fin, ou étant tout de Str.

0

Cette fonction est pas exactement ce dont vous avez besoin, mais il est assez proche:

J'espère qu'il est utile:

{ 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

Si vous avez la fonction comme ci-dessous

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; 

et appel comme ceci:

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

Vous ne pouvez pas tomber le moindre problème si vous l'appelez une seule fois. Mais si vous appelez cela en boucle (par exemple 1000 fois ou plus) d'abord en utilisant la fonction Pos (comme ci-dessous) étonnamment vous donner des performances supplémentaires

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; 
Questions connexes