自動型変換の罠

PHP で, 改行区切りの数値を処理しようとして, めっちゃはまったのでメモ.

下記のようなテキストファイルを読み込み, 最小値から最大値までをループといった処理をする場合,

test.txt

1
3
2
0

こんな感じになると思います.

<?php
$contents = file('./test.txt');
sort($contents, SORT_NUMERIC);
$min = min($contents);
$max = max($contents);

for ($i = $min; $i < $max; $i++) {
    // some processing...
}
?>

このように, テキストファイルを読み込み, 配列に代入した段階では, まだ改行コードが残っています.
しかし, PHP の賢い(?)自動型変換機能は, 改行コードが含まれていようと, 数値とみなしてソートまでしてくれます.

<?php
$contents = file('./test.txt');
sort($contents, SORT_NUMERIC);
var_dump($contents);
array(4) {
  [0]=>
  string(2) "0
"
  [1]=>
  string(2) "1
"
  [2]=>
  string(2) "2
"
  [3]=>
  string(2) "3
"
}
?>

もちろん, 改行コードが含まれていようが, 最小値, 最大値も求めてくれます.

<?php
$min = min($contents);
$max = max($contents);
var_dump($min);
var_dump($max);
string(2) "0
"
string(2) "3
"
?>

比較演算子も完璧です.

<?php
var_dump($min < $max);
bool(true)
?>

しかし, 大きな罠が...

<?php
for ($i = $min; $i < $max; $i++) {
    // some processing...
}
?>

上記のように, for でループさせようとした場合, $i < $max で, ループの条件を評価するまでは良いんです.

<?php
$min = min($contents);
var_dump($min);
string(2) "0
"
$min++;
var_dump($min);
string(2) "0
"
?>

このように, 改行コードが含まれている場合, インクリメント演算子(++)で, インクリメントできません...

結果, 冒頭のプログラムは無限ループに陥ります(失笑)

ちなみに, 下記のように int にキャストするか trim してやれば問題ないです.

<?php
$min = (int) min($contents);
$min++;
var_dump($min);
int(1)
?>
<?php
$min = trim(min($contents));
$min++;
var_dump($min);
int(1)
?>