前回のおさらい
PHPのfscanfの戻り値
パラメータが2つだけ
fscanf(STDIN,"%d %d");
戻り値は配列パラメータにオプション指定有り
fscanf(STDIN,"%d %d",$a,$b);
戻り値は代入された値の数
パターンマッチしないケースも含めて表にまとめるとこうなる
入力 | パターン | 正常性 | オプ無 | オプ有 |
---|---|---|---|---|
HKT 48 | "%d %d" |
array(null,null) |
0 |
|
48 HKT | "%d %d" |
array(48,null) |
1 |
|
HKT HKT | "%d %d" |
array(null,null) |
0 |
|
48 48 | "%d %d" |
array(48,48) |
2 |
|
(空行) | "%d %d" |
null |
-1 |
パラメータにオプションを指定したときの謎動作
たとえば、標準入力を以下の通りとする。
HKT 48
48 HKT
HKT HKT
48 48
これをlist()を使って、$a
,$b
に値を格納して、$a
と$b
の状態を確認する。
<?php
list($a,$b)=fscanf(STDIN,"%d %d");
echo "a=",$a,",b=",$b,PHP_EOL;
list($a,$b)=fscanf(STDIN,"%d %d");
echo "a=",$a,",b=",$b,PHP_EOL;
list($a,$b)=fscanf(STDIN,"%d %d");
echo "a=",$a,",b=",$b,PHP_EOL;
list($a,$b)=fscanf(STDIN,"%d %d");
echo "a=",$a,",b=",$b,PHP_EOL;
list($a,$b)=fscanf(STDIN,"%d %d");
echo "a=",$a,",b=",$b,PHP_EOL;
a=,b=
a=48,b=
a=,b=
a=48,b=48
a=,b=
fscanfの戻り値を踏まえると、期待通りの動作といえる。
さて、いよいよ謎動作。fscanfのオプションを活用して、$a
、$b
の状態を確認すると実に気持ち悪い。
<?php
fscanf(STDIN,"%d %d",$a,$b);
echo "a=",$a,",b=",$b,PHP_EOL;
fscanf(STDIN,"%d %d",$a,$b);
echo "a=",$a,",b=",$b,PHP_EOL;
fscanf(STDIN,"%d %d",$a,$b);
echo "a=",$a,",b=",$b,PHP_EOL;
fscanf(STDIN,"%d %d",$a,$b);
echo "a=",$a,",b=",$b,PHP_EOL;
fscanf(STDIN,"%d %d",$a,$b);
echo "a=",$a,",b=",$b,PHP_EOL;
a=,b=
a=48,b=
a=48,b= ← a=,b= じゃないの?
a=48,b=48
a=48,b=48 ← a=,b= じゃないの?
上書きしないで値を使いまわしてる!
これによって困ること
while(!feof(STDIN)){
fscanf(STDIN,"%d %d",$a,$b);
if($a>0 and $b>0){
echo "Yes",PHP_EOL;
}else {
echo "No",PHP_EOL;
}
}
No
No
No
Yes
Yes <= Noだろが!!
回避方法
1. 初期化してあげる
<?php
while(!feof(STDIN)){
fscanf(STDIN,"%d %d",$a,$b);
if($a>0 and $b>0){
echo "Yes",PHP_EOL;
}else {
echo "No",PHP_EOL;
}
$a=$b=null;
}
2. リストを使う
<?php
while(!feof(STDIN)){
list($a,$b)=fscanf(STDIN,"%d %d");
if($a>0 and $b>0){
echo "Yes",PHP_EOL;
}else {
echo "No",PHP_EOL;
}
}
3. 空行なら処理終了
<?php
while(list($a,$b)=fscanf(STDIN,"%d %d")){
if($a>0 and $b>0){
echo "Yes",PHP_EOL;
}else {
echo "No",PHP_EOL;
}
}
or
<?php
while(fscanf(STDIN,"%d %d",$a,$b)>-1){
if($a>0 and $b>0){
echo "Yes",PHP_EOL;
}else {
echo "No",PHP_EOL;
}
}
and so on...