大学時代に初めてPiazaの問題を解き始めたとき、私は思いました。
「標準入力ってなんやねん???」と。
PHPの問題以前に、「標準入力とは何か」「具体的な標準入力の書き方」が分からなかったのです。
そのため、自分で調べたり勉強して、現在では標準入力についてある程度は理解することができました。
そこで今回は、私の学びを共有します。具体的には、以下の二つの項目について解説します。
- 標準入力とは何か
- 標準入力の書き方テンプレ【PHP】
少しでも参考になれば幸いです。
標準入力・標準出力とは何か?
まずは、標準入力・標準出力とは何か?について説明していきます。
標準入力とは?
標準入力(standard input, stdin)とは、プログラムに渡される値やデータの標準(デフォルト)の入力元のことです。そして大抵の場合、「標準の入力元」は「キーボード」を指します。
つまり、「データは標準入力により渡されます」=「データはキーボードから入力されます」ということです。
Paizaの場合だと、標準入力で必要なデータが渡されるため、問題を解く前にその入力値を受け取る処理を記述する必要があります。
標準出力とは?
標準出力とは、プログラムの実行結果の標準(デフォルト)の出力先のことです。そして大抵の場合、「標準の出力先」は「画面」を指します。
つまり、標準出力とは、「プログラムで記述、処理した結果等を画面に表示すること」です。
「標準入力・標準出力」は名前だけ見ると難しく感じますが、ザックリ「標準入力=キーボードから値を入力」「標準出力=画面にプログラムの結果を出力」と理解しておくくらいで良いと思います。
【PHPで標準入力の値を取得】基本となるソースコード
PHPで標準入力された値を受け取るための基本コードを解説しておきます。
こちらです。
$stdin = trim(fgets(STDIN));
説明としてはこんな感じです。
- STDIN:標準入力を表す定数。自動的に標準入力の値が入る
- fgets():第一引数に指定したファイルポインタから1行取得し、その文字列を返す
- trim():第一引数に指定した文字列の先頭および末尾にあるホワイトスペースを取り除き、その文字列を返す
単純に単一の値を受け取るだけならこれでOKです。
しかし、実際には、複数行に渡る値などの複雑な形式で渡される場合がほとんどです。
そこで次に、そのような様々なパターンで値が渡された場合の受け取り方法について、テンプレを交えて解説していきたいと思います。
【PHP・標準入力】Paizaでも使えるテンプレまとめ
ここまでで「標準入力とは何か?」そして「標準入力を使うための基本的なコード」については理解できたと思います。
そこで次に、具体的にPaiza等で使える標準入力のテンプレをまとめます。
あくまで私の方法なので、効率が良いコードとは限りませんが、一応これで動かすことはできると思います。
数多ある書き方のうちの一例として参考にして頂けると幸いです。
今回紹介するのは以下のパターンです。
- 入力値が横一行の場合
- 入力値が横一行かつそれぞれの値を分割させたい場合
- 入力値が縦一列の場合
- 入力値が縦複数列の場合
- 入力値が縦複数列かつ、行数を表す最初の値だけ取り除いて使いたい場合
- 入力値が縦複数列かつ各列の要素に隙間がない場合、行数を表す最初の値だけ取り除いた上で各列の要素を分割して使いたい
それぞれについて解説とサンプルコードを掲載します。
実際に利用する際にコメントが不要な場合は、only code以下の部分はコメントを省いたコードになっているので、そちらを使用して下さい。
1:入力値が横一行の場合
// 【1】入力値が横一行の場合
// 例:5 7 8
$stdin = trim(fgets(STDIN));
// $stdin = 5 7 8;
$stdin_array = explode(' ',$stdin);
// $stdin_array = [5, 7, 8];
// 後は配列の値を取り出して使うだけ
$sum = $stdin_array[0] + $stdin_array[1] + $stdin_array[2];
echo $sum;
//20
// only code
$stdin_array = explode(' ',trim(fgets(STDIN)));
2:入力値が横一行かつそれぞれの値を分割させたい場合
// 【2】入力値が横一行かつそれぞれの値を分割させたい場合
// 例:98 75 -> 9 8 7 5に分割したい
$stdin = trim(fgets(STDIN));
$stdin_array = explode(' ', $stdin);
// $stdin_array = [98, 75];
//それぞれの値を変数 a,bに代入。
$first_num = $stdin_array[0];
// 98
$second_num = $stdin_array[1];
// 75
// それぞれの値を分割して、配列として代入する
// $first_numを分割 -> $first_num_array=[9,8]
$first_num_array = str_split($first_num);
// $second_numを分割 -> second_num_array=[7,5]
$second_num_array = str_split($second_num);
// only code
$stdin_array = explode(' ', trim(fgets(STDIN)));
$first_num_array = str_split($stdin_array[0]);
$second_num_array = str_split($stdin_array[1]);
3:入力値が縦一列の場合
// 【3】入力値が縦一列の場合
// 例:
// 5
// 7
// 8
// 標準入力を一行ずつ配列に代入
while ($stdin = trim(fgets(STDIN))) {
$stdin_array[] = $stdin;
}
// $stdin_array = [5,7,8]
// only code
while ($stdin = trim(fgets(STDIN))) {
$stdin_array[] = $stdin;
}
4:入力値が縦複数列の場合
// 【4】入力値が縦複数列の場合
// 例:
// 5 8
// 7 1
// 8 2
while ($stdin = trim(fgets(STDIN))) {
$stdin_array[] = $stdin;
}
// $stdin_array = [5 8,7 1,8 2]
// 配列の各要素をさらに分解
$stdin_each_value = [];
foreach ($stdin_array as $value) {
// array_mergeでそれぞれの配列を足し合わせる
$stdin_each_value = array_merge($stdin_each_value, explode(' ', $value));
}
// $stdin_each_value = [5,8,7,1,8,2]
// only code
while ($stdin = trim(fgets(STDIN))) {
$stdin_array[] = $stdin;
}
$stdin_each_value = [];
foreach ($stdin_array as $value) {
$stdin_each_value = array_merge($stdin_each_value, explode(' ', $value));
}
5:入力値が縦複数列かつ、行数を表す最初の値だけ取り除いて使いたい場合
// 【5】入力値が縦複数列かつ、行数を表す最初の値だけ取り除いて使いたい場合
// 例:
// 2
// s 1 2 3 4 5
// s 1 2 3 4 5
// ↓
// 最初の2を取り除いた上で[s,1,2,3,4,5]としたい
// 標準入力を一行ずつ配列に代入
while ($stdin = trim(fgets(STDIN))) {
$stdin_array[] = $stdin;
}
// $stdin_array = [2, s 1 2 3 4 5, s 1 2 3 4 5]
// for文でi=0の配列の最初の要素だけ取り除く
$stdin_line_value = [];
for($i = 1; $i <= $stdin_array[0]; $i++){
// $stdin_array[$i] = s 1 2 3 4 5
// 配列にする
$each_line_array_value = explode(' ', $stdin_array[$i]);
// $each_line_array_value=[s,1,2,3,4,5]
// この中で各列の各要素を使える
// また、$stdin_line_valueに入れることで、whileの外で連想配列として
// 各列の値を使うことも可能
$stdin_line_value[] = $each_line_array_value;
}
// $stdin_line_value = [[s,1,2,3,4,5], [s,1,2,3,4,5]]
// only code
while ($stdin = trim(fgets(STDIN))) {
$stdin_array[] = $stdin;
}
$stdin_line_value = [];
for ($i = 1; $i <= $stdin_array[0]; $i++) {
$stdin_line_value[] = explode(' ', $stdin_array[$i]);
}
6:入力値が縦複数列かつ各列の要素に隙間がない場合、行数を表す最初の値だけ取り除いた上で各列の要素を分割して使いたい
// 【6】入力値が縦複数列かつ各列の要素に隙間がない場合、行数を表す最初の値だけ取り除いた上で各列の要素を分割して使いたい
// 例:2
// 1234
// 1234
// 標準入力を一行ずつ配列に代入
while ($stdin = trim(fgets(STDIN))) {
$stdin_array[] = $stdin;
}
// $stdin_array = [2,1234,1234]
// for文でi=0の配列の最初の要素だけ取り除く
$stdin_line_value = [];
for ($i = 1; $i <= $stdin_array[0]; $i++) {
// $stdin_array[$i] = 1234
// str_split関数により、それぞれの数字を分割して、配列として$each_line_array_valueに代入
$each_line_array_value = str_split($stdin_array[$i]);
// $each_line_array_value=[1,2,3,4]
// 各列の配列を代入して連想配列として扱う
$stdin_line_value[] = $each_line_array_value;
}
// $stdin_line_value = [[1,2,3,4],[1,2,3,4]]
// only code
while ($stdin = trim(fgets(STDIN))) {
$stdin_array[] = $stdin;
}
$stdin_line_value = [];
for ($i = 1; $i <= $stdin_array[0]; $i++) {
$stdin_line_value[] = str_split($stdin_array[$i]);
}
おわりに
今回は標準入力(標準出力)の意味と、Paizaでも使える、PHPで標準入力された値を受け取るためのテンプレを紹介しました。
少しでも参考になっていれば幸いです。
