tetsunosukeのnotebook

tetsunosukeのメモです

与えられた変数が数字かどうか調べる のに ctype_digitを使って死んだ話

プログラムの受け入れテストをしていて、どうしても通らない箇所があって、こんな感じに書いてあったのです

if (ctype_digit($num)) {
    // 通ってくれない処理
}

まあもっと言うとこんな

$list = array(
    '1' => 10,
    '2' => 20,
);

foreach($list as $key => $value) {
    if (ctype_digit($key)) {
        // 通ってくれない処理
    }
}


というわけで

<?php
$list = array(
    '1' => 10,
    '2' => 20,
);

foreach($list as $key => $value) {
    var_dump($key);
    var_dump(ctype_digit($key));
}
int(1)
bool(false)
int(2)
bool(false)

ファッ?!

ああ、これはPHPの配列のキーがいつのまにかintegerになっちゃう問題なのねー。

というわけで ctype_digitは

この関数を活用するには string を渡さなければなりません。

ってやつだよ。

で、この$listはもともとこんな風にベタでは書いてなくて、実際には'98765432' みたいな値が入る。なので、動作テスト時にこれを書いた人は通ったんだろう。

で、なんで通るの。

<?php
var_dump(ctype_digit(98765432));
bool(true)

なんとっ

たとえば integer を渡すと、期待する結果にならない可能性があります。 HTML フォームに入力された整数値は、integer ではなく string 型で返されます。 マニュアルの 型 についての節を参照ください。

ああこれなのね

var_dump(ctype_digit(47));
var_dump(ctype_digit(48));
bool(false)
bool(true)

うわー。

<?php
for( $i = 1; $i <= 100; $i++) {
    if (ctype_digit($i) === TRUE) {
        echo 'T';
    } else {
        echo 'F';
    }

    if( $i % 10 === 0 ) {
        echo PHP_EOL;
    }
}
FFFFFFFFFF
FFFFFFFFFF
FFFFFFFFFF
FFFFFFFFFF
FFFFFFFTTT
TTTTTTTFFF
FFFFFFFFFF
FFFFFFFFFF
FFFFFFFFFF
FFFFFFFFFF

見事に48~57までナイジャー・モーガン

var_dump(chr(47));
var_dump(chr(48));
var_dump(chr(49));
var_dump(chr(57));
var_dump(chr(58));
string(1) "/"
string(1) "0"
string(1) "1"
string(1) "9"
string(1) ":"

あーなるほどねー。

  • 128 から 255 までの整数値を渡すと、ひとつの文字の ASCII 値とみなします (負の値には 256 を足して、拡張 ASCII の範囲に収まるようにします)。 それ以外の整数値は、10 進数を含む文字列とみなします。


あぶねーなーもう