読者です 読者をやめる 読者になる 読者になる

JOI 予選の入出力について

今日 12 月 16 日は情報オリンピックの予選ですね!!!
ということで、あんまり見かけなかった入出力について書こうと思います。

はじめに

情報オリンピックの予選ではプログラムを提出し、向こうのサーバーで実行して正誤判定をするのではなく、与えられた入力ファイルに対する出力ファイルを提出します。
で、これで問題なのがファイルで与えられてファイルで出力するってところ。
標準入力でもなければ標準出力でもないです。わーたいへん!
ちなみに:標準入力は cin / scanf 、標準出力は cout / printf です。(たぶん
予選当日になってファイルで入出力する方法調べるのめんどい!ファイルで入出力させるために色々書くのめんどい!というあなたにリダイレクトという技を教えようと思います。
(あと、コードを書いてファイル入出力する感じでやってしまうといちいちファイル名を書き直して実行しなおさないといけないのでめんどうというのもあります)(頭良い方法があるのかもしれないが知らない)

リダイレクトとは

リダイレクトとは:プログラムの入力元や出力先を通常とは違うものに変更すること。

リダイレクト【redirect】

つまりは、コードでは標準入力 / 出力しているけど、実行する時にファイルに入力 / 出力するように出来るよってことですね。
実際に書いた時の実行例を一度示します。あとあときちんと解説します。
(環境は OS X なので Windows とは実行ファイル等の名前が違うと思いますが、Windows でもリダイレクトは出来るとおもいます)

li_saku $ c++ joi_yo_1.cpp
li_saku $ ./a.out
# 適当にサンプルを実行する、大丈夫そうなので提出用の出力ファイルを作る
li_saku $ ./a.out < 2012-yo-t1-in1.txt > 2012-yo-t1-out1.txt
li_saku $ ./a.out < 2012-yo-t1-in2.txt > 2012-yo-t1-out2.txt
li_saku $ ./a.out < 2012-yo-t1-in3.txt > 2012-yo-t1-out3.txt
li_saku $ ./a.out < 2012-yo-t1-in4.txt > 2012-yo-t1-out4.txt
li_saku $ ./a.out < 2012-yo-t1-in5.txt > 2012-yo-t1-out5.txt

こんな感じでしょうか。サンプルの下り書く必要あったのかは疑問ですが一応。
で、この部分がリダイレクトです。

li_saku $ ./a.out < 2012-yo-t1-in1.txt > 2012-yo-t1-out1.txt
li_saku $ ./a.out < 2012-yo-t1-in2.txt > 2012-yo-t1-out2.txt
li_saku $ ./a.out < 2012-yo-t1-in3.txt > 2012-yo-t1-out3.txt
li_saku $ ./a.out < 2012-yo-t1-in4.txt > 2012-yo-t1-out4.txt
li_saku $ ./a.out < 2012-yo-t1-in5.txt > 2012-yo-t1-out5.txt

ファイル名を見て分かる通り、2012-yo-t1-in1.txt が入力ファイル、 2012-yo-t1-out1.txt というのが出力ファイルです。
この時のコードの中身はファイル入出力なんかしていなくて、普通に使うように標準入出力してます。
「<」の右側にあるファイルを標準入力として実行ファイルに与えて、「>」の右側にあるファイルに標準出力をする、といった感じです。
(ちなみに、出力ファイルに存在しないファイル名を指定した場合そのファイルを作ってくれます。また、存在するファイル名を指定した場合は中身が上書きされます)
リダイレクトを使うと、ファイル入出力のことなんか考えずに問題を解くことができますね!でも!!!
ファイルが 5 つもある!!!おおい!!! 5 回も実行したらどこかで数字間違えるよ!!!という人居ませんか?(わたしはそうです)
ということでシェルスクリプト書きました。

シェルスクリプト

ファイル名を固定していますが、例年この形なので今年もきっとこれだと思います。そうでなかったら、合うように調整してください。

OS X, Cygwinなどなど

書いたものはこれです。→ https://gist.github.com/4298378
cygwin で使用するときは、a.out を a.exe に書き換えてください。 a.exe でなく、問題毎に実行ファイルの名前を変えている場合はそのファイル名にしてください。)
左の方に Download とかいうボタンがあるとおもうのでそこからダウンロードして、名前を「[任意の英数字からなる文字列].sh」にしてください。拡張子は固定です。そうじゃないと動かないと思います。
使い方は以下の通りです。(このファイルが redirect.sh と保存されているとします。)

li_saku $ sh redirect.sh 1

これだけです。
sh というのはこれを実行するのに必要なもので、 redirect.sh はファイル名です。そのあとの 1 というのは問題の番号を表しています( 1 〜 6 のどれか)。
もし cygwin でエラーが出た場合、ファイルの中の ./a.exe という部分を a.exe に変えると上手くいくかもしれません。(手元に実行環境がないので未確認)

windows のコマンドプロンプト(cmd.exe)

スクリプトファイルはこれです。→ https://gist.github.com/4298328
実行ファイルを a.exe という名前で指定していますが、問題毎に実行ファイルの名前を変えている方は適宜変更して対応してください。
左の方に Download とかいうボタンがあるとおもうのでそこからダウンロードして、名前を「[任意の英数字からなる文字列].bat」にしてください。拡張子は固定です。そうじゃないと動かないと思います。
使い方は以下の通りです。(このファイルが redirect.bat と保存されているとします。)

li_saku $ redirect.bat 1

これだけです。
redirect.bat はファイル名です。そのあとの 1 というのは問題の番号を表しています( 1 〜 6 のどれか)。

使う時の注意など

これを一度実行するだけで、入力ファイル 5 つ全てに対する出力ファイルが生成されます。
なので、同じフォルダ内に入力ファイルがすべて入っている必要があります。
また、redirect.sh / redirect.bat の後に与える数字は一つじゃないとダメです。エラー処理なんかしてないので、各自気を付けてください。

おわりに

情報オリンピックの予選、がんばってください、応援してます!!!