新着情報

Information

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.findString.indexという二種類のメソッドがあるようです。findは文字列が見つからないときに-1を返しますが、indexはなんとValueErrorという例外を投げるようです。indexメソッドは文字列が含まれない場合には呼ぶべきではない、ということかもしれません。このあたりはRubyの考えと似ている気がします。

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

2011年11月10日 | スタッフブログ