PHPで、空白区切りの数値を数値として読む
ちょっとPHPをいじる機会があったのでメモ的に。
発端
空白区切りでN個(既知)の数値を読み込む場合、Cならば私はこう書く。
// 3個の整数値を読み込む場合 #include <stdio.h> int main(void) { int a[3], i; for( i=0; i<3; i++) scanf("%d",&a[i]); for( i=0; i<3; i++) printf("%d ",a[i]); }
予め判明している型でN回scanf()すれば良い。
しかしPHPで同じことをやろうと思ったら、こんなことにすら戸惑ったので
備忘録としてまとめておく。
PHPの場合
PHPで標準入力から読み込む場合、fgets(STDIN)を使うのだが、
数値も空白も一緒くたにstring型として読み込むので困る。
<?php $input = fgets(STDIN); //標準入力からinputに読込 print("type:".gettype($input)." "); //inputの変数型を表示 print("strlen:".strlen($input)."\n"); //inputのstring型としての長さを表示 for( $i = 0; $i<strlen($input); $i++){ echo "\$input[".$i."]:"; if($input[$i]==" ") // input[i]が空白のとき、"Space"と表示 echo "Space\n"; else if($input[$i]=="\n") // input[i]が改行のとき、"New Line"と表示 echo "New Line\n"; else echo $input[$i]."\n"; // それ以外は、input[i]を表示 } ?>
入力(1)
100 200 300
出力
type:string strlen:12 $input[0]:1 $input[1]:0 $input[2]:0 $input[3]:Space $input[4]:2 $input[5]:0 $input[6]:0 $input[7]:Space $input[8]:3 $input[9]:0 $input[10]:0 $input[11]:New Line
こんな風に。
そういうときには、指定した文字列を正規表現で分割するpreg_split関数を使う(split関数は5.3.0で非推奨になったらしい)。
正規表現でどう表すかは今回は置いておくとして、空白で分割するときは次のようにするといいらしい。
<?php $input = preg_split('/ /', trim(fgets(STDIN))); //空白区切りで標準入力からinputに読込 print("type:".gettype($input)." "); //inputの変数型を表示 print("count:".count($input)."\n"); //inputの配列としての長さを表示 for( $i = 0; $i<count($input); $i++){ echo "\$input[".$i."]:"; echo $input[$i]."\n"; // } ?>
実行結果
type:array count:3 $input[0]:100 $input[1]:200 $input[2]:300
これでちゃんと数値として読み込まれてますね。
ちなみに、preg_split()の前にtrim()を挟んでいるのは、入力の末尾の改行等を取り除くためです。
文字列の場合はexplode()を使うらしいので、そっちもいつか記事として書きたいなぁ。
執筆中に降って湧いた新たな謎
これを書いてるときに「string型だからそのままじゃ計算出来ないし」と書こうとしていたのだが、
一応検証してみることにした。
<?php $input = fgets(STDIN); //標準入力からinputに読込 print("type:".gettype($input)." "); //inputの変数型を表示 print("strlen:".strlen($input)."\n"); //inputのstring型としての長さを表示 for( $i = 0; $i<strlen($input); $i++){ echo "\$input[".$i."]:"; if($input[$i]==" ") // input[i]が空白のとき、"Space"と表示 echo "Space\n"; else if($input[$i]=="\n") // input[i]が改行のとき、"New Line"と表示 echo "New Line\n"; else echo $input[$i]."\n"; // それ以外は、input[i]を表示 } echo "input[0]:".$input[0]; echo " input[4]:".$input[4]; $sum = $input[0] + $input[4]; // input[0]とinput[4]の和を計算 echo "input[0]+input[4]=".$sum."\n"; ?>
実行結果(入力は(1)と同じ)
type:string strlen:12 $input[0]:1 $input[1]:0 $input[2]:0 $input[3]:Space $input[4]:2 $input[5]:0 $input[6]:0 $input[7]:Space $input[8]:3 $input[9]:0 $input[10]:0 $input[11]:New Line input[0]:1 input[4]:2 input[0]+input[4]=3
できるのかよ!
string型じゃなかったんかアンタ…。
文字列の場合
文字列の場合はexplode()を使う。(splitでもできるだろうけど)
<?php $input = trim(fgets(STDIN)); $words = explode(" ", $input); print_r($words); ?>
入力
hoge fuga piyo foo bar
出力
Array ( [0] => hoge [1] => fuga [2] => piyo [3] => foo [4] => bar )
数値と文字列の混合
じゃあ数値と文字列の混合はどうするか。
splitを使ってみる。
<?php $input = preg_split('/ /', trim(fgets(STDIN))); //空白区切りで標準入力からinputに読込 print("type:".gettype($input)." "); //inputの変数型を表示 print("count:".count($input)."\n"); //inputの配列としての長さを表示 for( $i = 0; $i<count($input); $i++){ echo "\$input[".$i."]:"; echo $input[$i]."\n"; // } $sum = $input[1] + $input[3] + $input[5]; echo $sum; ?>
入力
hoge 100 fuga -50 piyo 3.1415
出力
type:array count:6 $input[0]:hoge $input[1]:100 $input[2]:fuga $input[3]:-50 $input[4]:piyo $input[5]:3.1415 53.1415
splitで問題なさそうですね。