Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What are the problem?
@kakudaisuke

fgetsとかSTDINとか標準入力がわからなくてPaizaスキルチェックを始められない方へ

はじめに

Paizaでは問題や解答のヒントをSNSなどに記載することは禁じられています。本記事は、その問題を解く以前の大前提を整理したもので、一般に公開されている「値取得・出力サンプルコード」を中心に解説したものですので、禁止事項に当たらないと認識していますが、万が一問題を指摘されたら非公開とします。

さて、プログラミングを学び始めて、もっと実力を磨くために、問題集みたいなのないかなーと探してPaizaに辿り着いたまではいいものの、「標準入力?fgets?STDIN?何それ?」「標準入力の値の取得方法は下記ページのサンプルコードを参照ください。って言うから値取得・出力サンプルコード見たけど、意味不。」と、当初はDランクの問題ですら、60分以内に解けなかった僕が通ります。

私はPHPを学習しているので、PHP前提でこの記事を作成します。

上級者の方、ツッコミや補足情報あれば、ぜひお願いします。

標準入力

標準入力とは、ここでは、Paizaスキルチェックにおいて、Paiza側から渡されるデータのことです。現時点では、あなたのプログラムの整合性を確認するために、10パターンのデータを用意して、あなたが提出したプログラムをチェックします。そのデータはこの標準入力としてあなたのプログラムに読み込む準備をしておかなくてはなりません。

そこで必要なのが、(1)fgets関数と(2)STDINというオブジェクト(モノ)です。

fgetsとは

fgetsは関数でPHP公式では、下記のように定義されています。

fgets — ファイルポインタから 1 行取得する

ファイルポインタとは?

サーバーはファイルを扱うためにファイルポイントという専用のしおりを使います。 ファイルポインタは現在ファイルをどこまで読んだか、書いたかを示します。
http://www.standpower.com/php_analyz.html

STDINとは

標準入力のこと。STDINは変数みたいなもので、そこにPaiza側が用意した実際の値が入ってきます。

標準入力とは、コンピュータ上で実行されているプログラムが、特に何も指定されていない場合に標準的に利用するデータ入力元。
http://e-words.jp/w/%E6%A8%99%E6%BA%96%E5%85%A5%E5%8A%9B.html

まずは1行めをきちんと取り出す

仮に、下記のようなデータがSTDINとして与えられたとします。最終行には改行があります。

STDIN
1
2
3

この値を取得していくには、下記コードでできます。Paizaでも一番最初に既に用意されているコードですよね。当然ながら$input_lineは別に$iとかにしても同じです。

PHP
$input_line = fgets(STDIN);

出力結果↓

STDIN
1

わかりづらいですが、1の後に改行が入っています。
これはあまりよろしくないので、trim関数を使ってトリミングしてあげます。

trim — 文字列の先頭および末尾にあるホワイトスペースを取り除く

PHP
$input_line = trim(fgets(STDIN));

↑こうすると改行やスペースのない1が取り出せます。

複数行にまたがるデータを取り出す

今見たように、1行めを取り出すのは簡単でしたが、では2行め以降はどのように取り出したらいいのでしょうか。
fgets関数は「ファイルポインタから 1 行取得する」ので、処理を繰り返すと2行目以降も取り出すことができます。

PHP
$a = trim(fgets(STDIN));
$b = trim(fgets(STDIN));
$c = trim(fgets(STDIN));
$d = trim(fgets(STDIN));

echo = $a; //1
echo = $b; //2
echo = $c; //3
echo = $d; //データなし

↑このように2回目のfgetsは2行めを取ってきます。

また、Paizaでは複数行にわたるデータの最初の行は総データ数を渡してきて、2行目からが実際に処理するデータであることが多いです。下記↓のような例です。(しつこいですが、最終行には改行が入ってます。)

STDIN
3
1
2
3

↑データ自体は先ほどのデータと同じですが、1行めにデータ数の情報(データ3行あるよ〜)が挿入されています。この1行めの数字は、forやwhileの繰り返し構文の条件設定に使えます。

PHP
$input_line = trim(fgets(STDIN)); //$input_lineには3が代入される

for($i=0; $i < $input_line; $i++) { //←繰り返しの条件設定に使う
 //処理したい内容をここに
}

↑こうすれば0, 1, 2と3回for内の処理が繰り返されることになります。

また、そこで当然ながらデータを使うことになると思いますので、fgets(STDIN)をfor文の中に書いていきます↓。

PHP
$input_line = trim(fgets(STDIN)); //$input_lineには3が代入される

for($i=0; $i < $input_line; $i++) {
 $a = trim(fgets(STDIN)); //もう上で一行目の3は使われているので、二行目の値1から一行ずつ代入されていく
}

↑こうして、一行目のデータをデータ数として使用し、二行目以降を実際のデータとして取り出して料理していくわけですね。

ちなみにこちら↓がPaizaの値取得・出力サンプルコード、PHPバージョンです。引用します。こうして見るとプログラムの最初の3行はわかりやすくなったのではないでしょうか??4行目からは取得したデータを問題に合わせてコーディングしているだけです。

STDIN
2
2 5
3 4

PHP
$input_line = trim(fgets(STDIN));
for ($i = 0; $i < $input_line; $i++) {
    $s = trim(fgets(STDIN));
    $s = str_replace(array("\r\n","\r","\n"), '', $s);
    $s = explode(" ", $s);
    echo "hello = ".$s[0]." , world = ".$s[1]."\n";
}

最後に

超初歩的な内容ですが、自分が過去に躓いたポイントを整理できました。誰かのお役に立てると幸いです。ご指摘もどうぞよろしくお願いします。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What are the problem?