プログラムにおける入力と出力とはどのようなものでしょうか?
入力というと、どうしても「入ってくる何か特別なもの」というイメージが湧きませんか?
出力も同様に、「出て行く何か特別なもの」という感じがします。
プログラムにおいては、まちがいではありませんがもっと広い意味をもちます。
というわけで本記事では、入力と出力を解説します。
プログラムにおける入力と出力とは?
下の図をごらんください。
当たり前に入力と出力をあらわした図です。
プログラムから見た「入力」とは、キーボードから手入力した情報や、ファイルから読み込んだ情報も含まれます。
「出力」も同様で、画面への表示やファイルへのデータ出力も出力に含まれます。
「標準」の入出力 3種
Rubyの入出力に関して、標準〜というものは3種類あります。
標準入力
キーボードからの入力が標準入力です。入力は他にもありますが、何も指定しなければ標準入力になります。
標準出力
画面への出力が標準出力です。何も指定しなければ標準出力になります。
標準エラー出力
標準エラー出力とは何か?から解説しましょう。
名前から、何かのエラーのための出力というイメージを受けます。しかしそうではなく、単純にいえば「プログラムの結果以外に何かを出力」するのがエラー出力と理解してください。
標準エラー出力も、画面への出力です。
標準入出力をコードで確認
今まで解説してきたことを、ソースコードで確認しましょう。
標準入力 STDIN
gets(げっとえすと呼ぶ人が多いです)を使います。getsは本来IOクラスのオブジェクトを介して行うものです。
キーボードの入力を変数strに入れて、それを表示させましょう。
str = STDIN.gets puts str
実行後、画面がしばらく固まったような感じになります。そしてabcdeと入力してEnterキーを押すと以下の結果が返ります。
[実行結果]
abcde
strには改行コードが入ったままです。いろいろと不都合があるので、chompを使って改行コードを除去することも可能です。
str = STDIN.gets.chomp puts str
標準出力 STDOUT
同じように標準出力も試しましょう。
とはいうものの、すでに先ほど出てきています。putsを使います。これも正式な書き方でいきましょう。
画面が固まったようになったら入力待ち状態です。abcdeと入力してENTERキーを押してください。
str = STDIN.gets.chomp STDOUT.puts str
[実行結果]
abcde
ついでに、リダイレクトを解説します。
出力を標準以外の別の何かに振り向けることを、リダイレクトといいます。
この用語は、Rubyに限らず「別の出力に振り向ける」という意味で広く使われているので、ぜひ覚えておきましょう。
先の例でいくと、標準出力をファイルに振り向けるには>を使います。
str = STDIN.gets.chomp STDOUT.puts str
このプログラムをsample.rbという名前のファイルで保存します。
実行時、以下のようにしてください。
ruby sample.rb > sample.txt
実行しても何も変化がありません。入力待ち状態になっています。
abcdeと入力してENTERキーを押してください。
すると、sample.rbと同じディレクトリにsample.txtというファイルができて、その中身がabcdeとなっているはずです。
本来は標準出力である画面表示がされるはずです。ところが、画面に表示されるはずの内容が、sample1.txtに出力されたというわけです。
リダイレクトの雰囲気、つかんでいただけたでしょうか?
ファイルの入出力
ファイルからデータを読み込む、ファイルへデータを書き込む、という動作をみてみましょう。
ソースファイルと同じディレクトリに、sample1.txtというファイルが存在しているとします。
そしてその中身は、以下のとおりです。
aaaaaaa bbbbbbb ccccccc
ファイルからデータを読み込む
上記ファイルから、データを読み込んで画面に表示させましょう。
File.open("sample1.txt", "r") do |io| while line = io.gets puts line end end
[実行結果]
aaaaaaa bbbbbbb ccccccc
File.openで、ファイル名とモードを指定してファイルの内容を読み込みます。
今回は”r”の読み込みを指定しました。
また、each_linesで行数を取得できます。
File.open("sample1.txt", "r") do |io| while line = io.gets puts io.lineno.to_s + " : " + line end end
[実行結果]
1 : aaaaaaa 2 : bbbbbbb 3 : ccccccc
ファイルへデータを書き込む
今度はファイルへ書き込んでみましょう。
array = ["aaaaa", "bbbbb", "ccccc"] File.open("sample2.txt", "w") do |io| array.each do |str| io.puts str end end
実行後、sample2.txtというファイルが出来上がり、中身は以下のとおりになっているはずです。
[実行結果]
aaaaa bbbbb ccccc
ファイルポインタ
通常はファイルは先頭から読み込まれますが、自分で操作して任意の箇所から読み込むことも可能です。
現在どこを読んでいるかを指し示すものをファイルポインタといいます。
何も指定しなければ、先頭から順に進んでいきます。
これを操作して、任意の箇所を読み込んでみましょう。
File.pen("sample1.txt", "r") do |io| puts io.read(10) end
[実行結果]
aaaaaaa bb
改行コードも1文字として、先頭から10文字読み込むことができました。
ブロックでオープン、クローズを省略可
今まで普通に行ってきたファイル操作ですが、本来はファイルをオープンする、クローズするという操作が必要です。
doからendで囲われたブロックでファイルの操作を行うと、オープンとクローズが省略できるのです。
省略せずに書いてみましょう。
io = File.open("sample1.txt", "r") while line = io.gets puts io.lineno.to_s end io.close
複雑なことをしようとすると、ioクラスを使って細かな操作が必要になります。
今すぐにできるようになる必要はありませんが、ioクラスの存在だけでも知っておきましょう。
まとめ
本記事では、入出力について解説しました。
特にファイルからの読み込みや書き出しは非常に大事なので、いろいろと試して自分のモノにしておいてくださいね!