Prof A Olowofoyeku (The African Chief) wrote:
I have been trying to implement a "pos" function that only matches whole words. Below is my best effort. Is there a more efficient (or "better") way of implementing this? Thanks.
{ a "pos" function that matches whole words only } function PosInString (const sub, str : String) : Cardinal; Const nSeparators = ['a'..'z', 'A'..'Z', '0'..'9']; { non-separators }
BTW, what about the underscore?
Var i, j : Cardinal; begin result := 0;
Again, I'd strongly discourage using implicit `Result' unless absolutely necessary both syntactically and for Delphi compatibility. In this case, it's not necessary syntactically as it only appears on the LHS.
If (sub = '') or (str = '') then Exit;
BTW, `Pos' returns 1 if the substring is empty (meaning that an empty string matches anywhere). This may be a matter of definition -- if the first character of str is a letter it may seem wrong to find a word match there. Stricly speaking, one would have to find two subsequent separators (so that "nothing" is surrounded by separators), or a leading or trailing separator, but this case may not be important to you anyway.
i := pos (sub, str);
{ any match? } if (i = 0) then exit;
{ search for whole words only } result := i; j := length (sub) + i; if (i = 1) or ((i >1) and (Not (str [pred (i)] in nSeparators))) then begin if (j < length (str)) and (str [j] in nSeparators)
<=
(PosInString ('adam', 'adamx'))
then result := 0;
end else result := 0;
The two conditions can be merged into a single one. That's a matter of style.
However, if the first match is not a word, you might want to search again (PosInString ('adam', 'the adamant adam')). To do this, you'll need a loop and something like `PosFrom' (or `Pos' applied to a substring). In this case merging the conditions will help.
Frank