概要
ある日、for文の式2の値がtrueの時続行なのか、falseの時続行なのかをど忘れした私が、PHP公式ドキュメントのfor文を読んでいました。
PHP: for - Manual
一番下のUser Contributed Notesを読んでいた時、奇妙なコメントが
Looping through letters is possible. I'm amazed at how few people know that.
for($col = 'R'; $col != 'AD'; $col++) {
echo $col.' ';
}
returns: R S T U V W X Y Z AA AB AC
Take note that you can't use $col < 'AD'. It only works with !=
Very convenient when working with excel columns.
要訳すると
「文字をループできるって知ってる人意外と少ないよね。
(例文)
ちなみに < で比較はしないでね != でやるといいよ。
エクセルのカラムとかに使うと超便利!」
・・・文字をループって何?
検証してみた
つまり動作を分解して考えると
文字列"R"に対して1を加えると文字列"S"になる(次の文字を表示する)
ということになっていると仮定できる。
ちなみに文字の比較については、私が個人的に以前usort()をで色々やったときにお世話になったので今回は触れない。
詳しくは↓を読んでください。
PHP: 比較演算子 - Manual
てわけで、ideone を使っていろんな方法でやってみた。
for($col = 'R'; $col != 'AD'; $col++) {
echo $col.' ';
}
//returns: U V W X Y Z AA AB AC
コメント通りの動作。
$b = "AA";
$c = $b + 1;
echo $c;
//return: 1
あれ、1を足すとただの数値の1になる・・・
$b = "AA";
echo ++$b;
//return: AB
for文通りの動作になっている。
$b = "string";
$c = "AA";
echo (int)$b; //0
echo (int)$c; //0
最後に2つ目の例で文字列がどのように認識していたのか調べてみる。
どうやらintキャストされて0になったため、実際の足し算では「0 + 1」になり、答えが1になったようだ。
どうも、インクリメントの挙動が怪しいことに気がつく。
マニュアルを読むと・・・書いてあった!
つまりは、最初から加算子/減算子を読めばいいだけだったという結論だったわけですが、
PHP: 加算子/減算子 - Manual
PHP は、算術演算子で文字変数を扱った場合に C ではなく Perl の慣習に 従います。例えば、PHP や Perl では
$a = 'Z'; $a++;
の結果として$a
が 'AA' になりますが C ではa = 'Z'; a++;
の結果として a は '[' になります ('Z' の ASCII 値は 90、そして '[' の ASCII 値は 91 です)。 文字変数はインクリメントされることは可能ですがデクリメントは不可能であるということ、 またプレーンな ASCII 文字と数字 (a-z、A-Z、そして 0-9) のみがサポートされるということに注意しましょう。 その他の文字変数のインクリメント/デクリメントは何の効果もなく、元の文字列は変更されません。
ちなみにそこに乗っている例文が以下。
echo '== Alphabets ==' . PHP_EOL;
$s = 'W';
for ($n=0; $n<6; $n++) {
echo ++$s . PHP_EOL;
}
// 数字の挙動は異なります
echo '== Digits ==' . PHP_EOL;
$d = 'A8';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
$d = 'A08';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
== Characters ==
X
Y
Z
AA
AB
AC
== Digits ==
A9
B0
B1
B2
B3
B4
A09
A10
A11
A12
A13
A14
エクセルのカラムのタイプだけではないのも対応しているようです。
なにかその辺使えそうですね。