PHPで標準入力から値を受け取る(競技プログラミングとか)


40歳にリーチがかかってるおっさんがどういうわけか競技プログラミングに目覚めた

業務ではマネジメント(それもインフラ系)をしているので、つい、カッとなって、先月あたりから、競技プログラミングに目覚めました。

1か月も経ってようやく標準入力から値を受け取ることにも慣れてきたので、いったん、整理。

パターン別:値の受け取り方

1行から1つの値を受け取る場合

Sample Input

3

Code

$a=intval(trim(fgets(STDIN)));
//do something...

1行から複数の値を受け取る場合

Sample Input

1 2 3

Code

fscanf(STDIN,"%d %d %d",$a,$b,$c);
//do something...

別解

$input=explode(' ',trim(fgets(STDIN)));
$a=intval($input[0]);
$b=intval($input[1]);
$c=intval($input[2]);
//do something...

複数行から1行あたり複数の値を受け取る場合(行数あり)

Sample Input

3
1
2
3

Code

$n=intval(trim(fgets(STDIN)));
for($i=0;$i<$n;++$i){
    $a=intval(trim(fgets(STDIN)));
    //do something...
}

複数行から1行あたり複数の値を受け取る場合(行数あり)

Sample Input

3
1 2 3
4 5 6
7 8 9

Code

$n=trim(fgets(STDIN));
for($i=0;$i<$n;++$i){
    fscanf(STDIN,"%d %d %d",$a,$b,$c);
    //do something...
}

複数行から1行あたり1つの値を受け取る場合(行数なし)

Sample Input

1
2
3

Code

/* これだと0が入ってくるとループが止まってしまうのでNG
while($a=intval(trim(fgets(STDIN)))){
   //do something...
}
*/

//これなら大丈夫!
while(list($a)=fscanf(STDIN,"%d")){
    //do something...
}

/* これだと空行が混じると値を2回とってしまう
while(fscanf(STDIN,"%d",$a)){
    //do something...
}
*/

別解

/* これだと空行が0になる
while(!feof(STDIN)){
   $a=intval(trim(fgets(STDIN)));
   //do something...
}
*/

//これなら大丈夫!
while(strlen($a = trim(fgets(STDIN)))>0){
    $a = intval($a);
    //do something...
}

複数行から1行あたり複数の値を受け取る場合(行数なし)

Sample Input

1 2 3
4 5 6
7 8 9

Code

/* 空行が混じると同じ値を二度繰り返すのでNG
while(fscanf(STDIN,"%d %d %d",$a,$b,$c)){
   //do something...
}
*/

//空行対策版
while(list($a,$b,$c)=fscanf(STDIN,"%d %d %d")){
   //do something...
}

別解

/* 空行が混じると同じ値を二度繰り返すのでNG
while(!feof(STDIN)){
   fscanf(STDIN,"%d %d %d",$a,$b,$c);
   //do something...
}
*/

// これなら大丈夫(空行検出時はループしない)
while(strlen($input=trim(fgets(STDIN)))>0){
   sscanf($input,"%d %d %d",$a,$b,$c);
   //do something...
}

/* 空行は空行として扱いたい版
while(!feof(STDIN)){
   list($a,$b,$c)=fscanf(STDIN,"%d %d %d");
   //do something...
}
*/