2012-09-11 22 views
6

文字列に部分文字列が含まれているかどうかは特定の位置のみで確認できますか?文字列に単語が含まれていても、特定の位置にのみ含まれているかどうかを確認しますか?

例文字列:

あなたの好きな色は何ですか?私の私は、文字列は、私は通常これを行う特定の単語に含まれるかどうかを確認したい場合は、[好きな]色は

青です:私は必要なもの

var 
    S: string; 
begin 
    S := 'What is your favorite color? my [favorite] color is blue'; 
    if (Pos('favorite', S) > 0) then 
    begin 
    // 
    end; 
end; 

が単語の好きかどうかを判断することですがが文字列に存在していますが、[]記号の中に表示されている場合は無視されますが、上記のコードサンプルでは明らかにしていません。

我々はブール関数にコードを置くのであれば、いくつかのサンプルの結果は次のようになります。

TRUE:あなたの好きな色は何ですか?私の[私の好きな]の色は青です

TRUE:あなたの好きな色は何ですか?私の[何とか何とか]の色は青です

FALSE:あなたの何とか何とか色は何ですか?ワードのお気に入りは、それが彼らの内側にあるかどうか、[]記号の外で発見されたので、私の[いくつかのお気に入りの]色は青

最初の2つの標本が上記真です。

お気に入りの単語があっても、[]記号の中にのみ表示されるので、3番目のサンプルはfalseです。シンボルの外に存在するかどうかを確認する必要があります。

したがって、単語(この例ではお気に入り)が文字列に表示されるかどうかを判断する機能が必要ですが、単語が[]記号で囲まれている場合は無視されます。

+0

アイデア:1)文字列を '\ s'に分割し、4番目の要素を確認します。 2) 'お気に入り 'を確認します(単語の周囲のスペースに注意してください)。 3)文字列を疑問符「?」で分割し、「お気に入り」を保持しているかどうかを確認します。 –

+5

'['、検索が見つかりました ']'、 '[]'を含む中間を削除し、お気に入りを検索します。 –

+0

正規表現(XEに含まれるユニットを含む)を ''\ b' + wordtofind + '\ b''の正規表現で使用してください。あなたが気を付けなければならないのは、 'それはあなたのお気に入りですか? 'です。'?'はそれが一致しないでしょう。 –

答えて

8

私は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)), 0, 0, AWord, 
    SearchOptions)); 
end; 

ここで文字列操作なしポインタチャー反復を使用する機能の最適化されたバージョンです。以前のバージョンと比較して、これは、例えば、My [favorite color isのような閉じ括弧がない文字列がある場合を処理します。そのような文字列は、ブラケットがないためにTrueと評価されます。

原則として、文字列全体を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, soWholeWord); 
    if ACaseSensitive 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, 0, 0, AWord, 
     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, SubstrLen, 0, 0, AWord, 
    SearchOptions)); 
end; 
+1

偉大な答え、特に有用なのは、コメントの回答へのリンクです。何が起きているのかを少し分かりやすく理解しています。 –

+1

ありがとう!とにかく、正規表現は、あなたが必要とすることを実行するための正しい方法ですが(確かに簡単です)、一方で、これはこの特定のタスクのほうにまっすぐです(正規表現は少なくとも構文解析する必要があるので一致する前に式が一致します)。私は、たとえば、いくつかのパーサを構築するつもりがないなら、このマッチのような多くの似たようなタスクがどこにあるのでしょうか?このソリューションは、正規表現を含めるよりも軽いかもしれません。しかし主な理由は、私がこれを投稿したのは、ここでの答えのどれも純粋なDelphiを使用していないということです。 – TLama

7

regular expressionsには、look-aroundというものがあります。あなたのケースでは、否定的なlookbehindでそれを解決することができます:オープニングブラケットが先行していない限り、 "お気に入り"を望みます。それは次のようになります。ステップバイステップ

(?<!\[[^\[\]]*)favorite 

(?<!は、我々は、ブラケットを閉じたり開いていない\[、必要に応じてどれが続く以上のもののために、負の後読みプレフィックス探している:[^\[\]]*、負を閉じますlookbehindは)、その後はfavoriteとなります。

+0

私はあなたのものがエレガントで適切な解決策だと思います。 – diegoaguilar

0

私はあなたの問題を "大括弧で囲まれていない文字列を見つけてください"と言い換えることができると思います。それがあなたの問題を説明していれば、[^\[]favorite[^\]]のような単純な正規表現を使うことができます。

関連する問題