2011.11.10
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の考えと似ている気がします。
これだけ言語ごとに仕様が違っていると面白いです。
文字列検索は非常によく使われるのですが、だからこそ気をつけないとあぶないポイントかもしれません。