PHPの奇妙な冒険(文字列検索的な意味で
PHPを使っていて気付いたこと。
strpos
関数というのがあります。文字列の中に特定の文字列が現れる位置を取得する関数です。この関数の戻り値は位置を示す整数値で、見つからない場合はfalse
を返します。位置は先頭を0番目とするようです。
ということは……。
if (strpos('abcde', 'a')) { // ここにある処理は行われません }
めっちゃ困りました。0
は評価するとfalse
です。
これは、正しくはこうです。
if (strpos('abcde', 'a') !== false) { // ここにある処理は行われます }
でも、できるだけfalse
に対する比較を行いたくないです。
ところで、JavaのString.indexOf
メソッドは、文字列が見つからないときは-1
を返します。
ということは……。
function str_index($string, $search, $offset = 0) { $ret = strpos($string, $search, $offset); if ($ret === false) { $ret = -1; } return $ret; } // こう書きたい if (str_index('abcde', 'a') >= 0) { // ここにある処理は行われます } // あるいは if (str_index('abcde', 'z') < 0) { // 見つからなかったときの処理 }
これなら一貫性があって好きです。
ちょっと気になって他の言語も調べてみました。
Perlのindex
関数は文字列が見つからないときは-1
を返します。Javaと同じですね。
C++のSTLにあるString.find
メソッドは、文字列が見つからないときはnpos
という定数を返します。値はstatic_cast<size_type>(-1)
であり、大抵の場合0xffffffff
だったりします。当然これは0
より大きな値ですから、0
と比較すると危ないです。
RubyのString.index
メソッドは、文字列が見つからないときはnil
を返します。PHPのnull
相当のものです。更にString.include?
メソッドというものがあって、こちらは見つかったらtrue
、見つからなければfalse
を返します。文字列が存在するかどうかの判定にはinclude?
メソッドを使いましょう、ということですね。
PythonにはString.find
とString.index
という二種類のメソッドがあるようです。find
は文字列が見つからないときに-1
を返しますが、index
はなんとValueError
という例外を投げるようです。index
メソッドは文字列が含まれない場合には呼ぶべきではない、ということかもしれません。このあたりはRubyの考えと似ている気がします。
これだけ言語ごとに仕様が違っていると面白いです。
文字列検索は非常によく使われるのですが、だからこそ気をつけないとあぶないポイントかもしれません。