示例字符串:
What is your favorite color? my [favorite] color is blue
如果我想检查字符串是否包含特定单词,我通常会这样做:
var S: string; begin S := 'What is your favorite color? my [favorite] color is blue'; if (Pos('favorite',S) > 0) then begin // end; end;
我需要的是确定字符串中是否存在单词favourite,忽略它是否出现在[]符号中,上面的代码示例显然没有.
因此,如果我们将代码放入布尔函数中,一些示例结果将如下所示:
TRUE: What is your favorite color? my [my favorite] color is blue
TRUE: What is your favorite color? my [blah blah] color is blue
FALSE: What is your blah blah color? my [some favorite] color is blue
上面的前两个样本都是真的,因为在[]符号之外找到了收藏词,无论它是否在其中.
第三个样本是假的,因为即使有喜欢这个词,它只出现在[]符号内 – 我们应该只检查它是否存在于符号之外.
所以我需要一个函数来确定一个单词(在这个例子中是最喜欢的)是否出现在一个字符串中,但忽略了这个单词被包含在[]符号中的事实.
解决方法
Sertac's idea
关于删除括号括起来的字符串并在此之后搜索字符串.以下是通过搜索整个单词和区分大小写扩展的代码示例:
function ContainsWord(const AText,AWord: string; AWholeWord: Boolean = True; ACaseSensitive: Boolean = False): Boolean; var S: string; BracketEnd: Integer; BracketStart: Integer; SearchOptions: TStringSearchOptions; begin S := AText; BracketEnd := Pos(']',S); BracketStart := Pos('[',S); while (BracketStart > 0) and (BracketEnd > 0) do begin Delete(S,BracketStart,BracketEnd - BracketStart + 1); BracketEnd := Pos(']',S); BracketStart := Pos('[',S); end; SearchOptions := [soDown]; if AWholeWord then Include(SearchOptions,soWholeWord); if ACaseSensitive then Include(SearchOptions,soMatchCase); Result := Assigned(SearchBuf(PChar(S),StrLen(PChar(S)),AWord,SearchOptions)); end;
这是函数的优化版本,它使用指针字符迭代而不进行字符串操作.与以前的版本相比,当你有一个缺少结束括号的字符串时就会处理这种情况,例如My [最喜欢的颜色是.由于缺少括号,这样的字符串被评估为True.
原则是通过char遍历整个字符串char,当你找到开括号时,查看该括号是否有自己的结束对.如果是,则检查存储位置的子字符串是否包含搜索的单词.如果是,请退出该功能.如果不是,请将存储的位置移动到右括号.如果左括号没有自己的闭合对,则从存储位置搜索单词到整个字符串的末尾并退出该函数.
对于此代码follow this link的注释版本.
function ContainsWord(const AText,AWord: string; AWholeWord: Boolean = True; ACaseSensitive: Boolean = False): Boolean; var CurrChr: PChar; TokenChr: PChar; TokenLen: Integer; SubstrChr: PChar; SubstrLen: Integer; SearchOptions: TStringSearchOptions; begin Result := False; if (Length(AText) = 0) or (Length(AWord) = 0) then Exit; SearchOptions := [soDown]; if AWholeWord then Include(SearchOptions,soMatchCase); CurrChr := PChar(AText); SubstrChr := CurrChr; SubstrLen := 0; while CurrChr^ <> #0 do begin if CurrChr^ = '[' then begin TokenChr := CurrChr; TokenLen := 0; while (TokenChr^ <> #0) and (TokenChr^ <> ']') do begin Inc(TokenChr); Inc(TokenLen); end; if TokenChr^ = #0 then SubstrLen := SubstrLen + TokenLen; Result := Assigned(SearchBuf(SubstrChr,SubstrLen,SearchOptions)); if Result or (TokenChr^ = #0) then Exit; CurrChr := TokenChr; SubstrChr := CurrChr; SubstrLen := 0; end else begin Inc(CurrChr); Inc(SubstrLen); end; end; Result := Assigned(SearchBuf(SubstrChr,SearchOptions)); end;