複数行ある標準入力(STDIN)の取得方法を整理したい


オンラインでのプログラミングの問題やスキルチェックに挑戦していたら、標準入力というのに出会い、与えられる値が複数行に跨っている場合、取り出すことが出来なかったので、初心者感丸出しで対策方法をまとめてみます。(理解違いなどありましたら、ご指摘いただけますと幸いです。)

さて、例えば、下記のようなテキストファイルを読み込むプログラムを作るとします。

このように複数行に配置された値を取得するには、while();(処理を繰り返す)とfgets();(ファイルから1行取得する)の組み合わせが有効のようです。

index.php
<?php
// まずファイルを開きます。fopen関数の2つめのパラメータのrは、読み取り専用で開くの意。
$file = fopen('stdin.txt', 'r');

// ファイルの内容を一行ずつ取得するにはwhile()
if ($file) {
    while ($input_line = fgets($file)) {
        echo $input_line;
    }
}
?>

初心者にはif内の処理がやや複雑なので細かく整理します。

  • if($file) {}→もし$fileに値が入ってたら{}の処理をしてね。
  • while ($input_line = fgets($file)) {}$fileの1行めから、順番に1行ずつ値を取得してfgets()$input_lineに代入できる間whileは、{}の処理をしてね。要約すると、$fileに値がある行の数だけ{}の処理をしてね。
  • echo $input_file$input_lineを表示してねecho。つまりwhileの中の条件文は、ただの条件だけでなく実際に処理が行われているんですね。これは押さえておきたいポイントかと思います。

一旦これで出力結果見てみると、下のようになり、2行め以降の値も取得できました。

これを配列として取得、保管するにはこうします。

index.php
if ($file) {
    while ($input_line = fgets($file)) {
        $x[] = $input_line; //各行の値を変数xに代入、保管
    }
}

この$xをvar_dump();で見てみると下記のようになり、よ〜く見ると各値の後に半角スペースが入り込んでいます。最終行の89の後には入っていないので、どうやらこの半角スペースは「改行」のようです(上記データで最終行の後に改行はない)。

array(6) { [0]=> string(2) "4 " [1]=> string(3) "15 " [2]=> string(2) "3 " [3]=> string(2) "5 " [4]=> string(2) "7 " [5]=> string(2) "89" }

取得したかった値の後に、半角スペースが入ってしまっています。ただし!試しにこれをechoで単に表示したり、計算に使ってみると普通にできちゃいます。できちゃうんですね、意外。

index.php
echo $x[0]; //結果→4(この後に半角スペースなし)

echo $x[0] + $x[1]; //結果→19

しかし、半角スペースが入るのもあまりよろしくないかと思いますので、下記のように$xに代入する際にtrim()関数を添えてあげてホワイトスペースを取り除くのがいいと思われます。

index.php
if ($file) {
    while ($line = fgets($file)) {
        $x[] = trim($input_line);
    }
}

こうすると半角スペースはなくなって綺麗になります。

array(6) { [0]=> string(1) "4" [1]=> string(2) "15" [2]=> string(1) "3" [3]=> string(1) "5" [4]=> string(1) "7" [5]=> string(2) "89" }

最後にまとめとして、複数行ある標準入力の取得方法のコードをまとめておきます。

index.php
<?php

// ファイルパスの指定
$file = fopen('stdin.txt', 'r');

// ファイルの内容を一行ずつ配列に代入します
if ($file) {
    while ($input_line = fgets($file)) {
        $x[] = trim($input_line);
    }
}
// 配列で取得できたのであとは普段通りやればOK
echo $x[0]; //4
echo $x[1]; //15
echo $x[2]; //3
echo $x[3]; //5
echo $x[4]; //7
echo $x[5]; //89
?>

これで配列として取得できたので、あとは足すなり、かけるなり、焼くなり、煮るなり。

もしご指摘などございましたらありがたいです。