授業資料/10 の変更点


#contents

//  第 10 回 (Ruby 入出力)

* Ruby: 入力(input) [#p0446587]

さて,プログラムが「情報を処理する」機能を果たすには,情報の入出力機能が必要だ.

そこで,まずはインプット,すなわち,プログラムにデータを渡す方法について学ぼう.
インプットを行う方法は,大雑把にいって,

- 起動時にパラメータとして与える
- 「標準入力」という特別に定まった入力方法に対応する
- ファイルから読み込む
- プログラムが動いている時にインタラクティブにデータを与える

など,様々な方法がある.

いきなりたくさん学ぶと混乱するだろうから,今回は一つだけ学ぼう.

&br;&br;
** 起動時にパラメータとしてデータを受け取る: ARGV 変数 [#r754193b]

起動時にパラメータとしてデータをプログラムに与えることができる.
このとき,プログラム側では
&br;&br;
CENTER:&size(24){''変数 ARGV[0] で一つ目,ARGV[1] で二つ目, (以下同様) ''};
CENTER:&size(24){''の起動時パラメータを受け取れる.''};
&br;&br;

&ref(/materials/notes.png); 実習: 以下のサンプルを動かしつつ,理解しよう.

次のプログラム
#highlighter(language=ruby,number=on,cache=on){{
include Math

p "The 1st parameter is "
p ARGV[0]

p "The 2nd parameter is "
p ARGV[1]
}}
を例えば ''sample.rb'' というファイル名で保存したとして,
//
>  ''ruby -w sample.rb aaa bbb''
<
としてプログラムを動かしてみよう.
これは,このプログラムを動かすときに 1つ目のパラメータに ''aaa'' を, 2つ目のパラメータに ''bbb'' を与えたことになる.
すると,次のような出力が得られるはずだ.
//
  "The 1st parameter is "
  "aaa"
  "The 2nd parameter is "
  "bbb"

これを見ると,プログラム側で ''aaa'' と ''bbb'' を受け取れていることがわかる.
&br;
&ref(/materials/warning.png); ruby では " (ダブルクオーテーション)で囲った部分は ''文字列'' である.




&br;&br;
** ARGV は文字列扱い.数字には変換しないとね. [#ecb178c1]
** ARGV は文字列扱い.数字には変換しないとね. [#kd1a3801]
&br;

上の結果例を見るとわかるが,
&br;&br;
CENTER:&size(24){''ruby では ARGV[0], ... は文字列として扱われる.''};
&br;&br;

だから,数字をデータとして与えたいときは,プログラムで変換する必要がある.
サンプルを見よう.

''与えたパラメータ3つを足すプログラム'' 
#highlighter(language=ruby,number=on,cache=on){{
include Math

a = ARGV[0].to_i
b = ARGV[1].to_i
c = ARGV[2].to_i

p a+b+c
}}
を ''sample.rb'' という名前だと仮定して,
//
>  ''ruby -w sample.rb 3 8 2''
<
とプログラムを動かしてみると,出力 ''13'' が得られるはずだ.

&br;
&ref(/materials/warning.png); このプログラム中の,''.to_i'' というのは,変数を整数に変換する機能だ.
&br;
&ref(/materials/warning.png); 同様に,''.to_f'' とすると実数に変換される.
&br;

このように,

&br;&br;
CENTER:&size(24){''受け取った ARGV[0], ... が整数のつもりならば .to_i を,''};
CENTER:&size(24){''実数のつもりならば .to_f をつけて変換しておこう.''};
&br;&br;

&br;&br;
** 練習問題 [#o1c0bf8f]
** 練習問題 [#h8a79241]
&br;
引数として与えられた正整数(1つ)が偶数か奇数か判定して出力するプログラムを書いて動かそう.
そのプログラムファイル名を ''sample.rb'' とするならば,例えば
//
> ''ruby -w sample.rb 11''
<
と動かすと,
//
  11
  "is odd."

などと出力するようにしよう,ということだ.



&br;&br;
** ARGV が幾つあるかは ARGV.size で分かるよ [#c50808c9]
** ARGV が幾つあるかは ARGV.size で分かるよ [#w733dc85]
&br;

平均値を求めたい時など,与えるパラメータの数が決まっていない場合がある.
こういうときは,受け取ったパラメータの個数をその場で知ることで対処する.

具体的には,
&br;&br;
CENTER:&size(24){''ARGV.size でパラメータの個数がわかる.''};
&br;&br;

例えば,
#highlighter(language=ruby,number=on,cache=on){{
include Math

p ARGV.size
}}
として
//
>  ''ruby -w sample.rb a b c''
<
としてプログラムを動かしてみると,''3'' という出力が得られるはずだ.

&br;&br;
** 練習問題 [#dad09c2a]
** 練習問題 [#eee24a3b]
&br;
パラメータとして与えた複数の数の平均を出力するプログラムを書こう.
具体的には,例えば,
//
>  ''ruby -w sample.rb 3 23 4 8 9''
<
とすると
//
  9.4

と出力されるようにしようということである.

&ref(/materials/warning.png); この出力が ''9'' になってしまう人はどこかがおかしいので,「何が起きているのか」よく考えよう.
&br;
&ref(/materials/warning.png); 与える数がこの例のように5個とは限らない.6個でも3個でも100個でも? 大丈夫なようにプログラムしよう.


&br;&br;
* Ruby: 出力(output) [#a5e09c7b]
&br;
少しずつアウトプットについても学んでいこう.

&br;
** すこし綺麗な出力を: print 命令 [#q8d70c90]
これまで出力は簡単な ''p'' 命令のみで行ってきたが,整頓されていないので読みにくい.
そこで,もう少し読みやすい ''print'' 命令について学ぼう.

使い方は簡単で,
&br;&br;
CENTER:&size(24){'' print() の中に出力するものをカンマで区切って並べるだけ''};
&br;&br;

でけっこう読みやすく表示される.

&ref(/materials/warning.png); ただし,''\n'' という特殊な文字列を出力したときしか出力が改行されない.
だから,
&br;&br;
CENTER:&size(24){''出力を改行したいところで print 命令に文字列 \n を入れよう.''};
&br;&br;

以下のサンプルを見てみよう.
#highlighter(language=ruby,number=on,cache=on){{
include Math

a = 3.0
b = 8.0

print("a is ",a," and b is ",b,".\n")
print("Average is ", (a+b)/2, ".\n")
}}
このプログラムを動かすと,
//
  a is 3.0 and b is 8.0.
  Average is 5.5.

となるはずである.
&br;
&ref(/materials/warning.png); ''\'' という記号は,状況によっては ''¥'' 記号で表示されるので注意しよう.同じものだ.

&br;
ちなみに,上のプログラム例は
#highlighter(language=ruby,number=on,cache=on){{
include Math

a = 3.0
b = 8.0

print("a is ")
print(a)
print(" and b is ")
print(b)
print(".")
print("\n")

print("Average is ")
print((a+b)/2)
print(".")
print("\n")
}}
と書いても同じ出力になる.
この例だとわかりにくいだけだが,このように ''print'' 命令を分割した方がプログラムしやすいこともある.

&br;
&ref(/materials/notes.png); 実習: 
上で改良した「起動時に与えたパラメータの平均を求めるプログラム」を,''print'' 命令を使ってさらに改良して,出力を読みやすくしよう.
具体的には,例えば,
//
>  ''ruby -w sample.rb 3 23 4 8 9''
<
とすると
  Input: 3.0 23.0 4.0 8.0 9.0
  Average: 9.4

などと出力されるようにできればだいぶよい感じだ.

&br;&br;
** 出力をとっておく方法: パイプ & tee [#p3f3e325]
&br;

画面への出力はいずれ見えなくなってしまう.
ファイルに出力するプログラムの機能などについては後で学ぶので,ここでは 起動時にちょっと工夫するだけで ''画面とファイルに同時に出力させる簡単な'' 方法について学ぼう.

やり方は簡単で,
&br;&br;
CENTER:&size(24){''プログラムの起動時に''};
CENTER:&size(24){'' | tee 画面への出力を記録しておくファイルの名前''};
CENTER:&size(24){''を最後にくっつける''};
&br;&br;

だけでよい.

例を見てみよう.例えば,
//
>  ''ruby -w sample.rb 3 23 4 8 9''
<
とすると
  Input: 3.0 23.0 4.0 8.0 9.0
  Average: 9.4

と出力されるプログラムに対して,''output.dat'' という名前のファイルに結果を記録しておきたいとする.

その場合は,
//
>  ''ruby -w sample.rb 3 23 4 8 9 | tee output.dat''
<
とするだけで,画面にも,''output.dat'' というファイルの中にも
  Input: 3.0 23.0 4.0 8.0 9.0
  Average: 9.4

という結果が出力される.

&ref(/materials/warning.png); ちなみに,'' | tee -a ファイル名'' という風に ''-a'' をつけて使うと,ファイルの中身に出力を「追加」してくれる. 上手に使い分けよう.

* 今日の総仕上げ [#d4782677]

これまでに学んだ知識を使って,次のようなプログラムを作り,結果を ''output.dat'' という名前のファイルに記録しよう.
そのプログラムとは,次の条件を満たすものである.

+ 起動時にパラメータとして整数 ''n'' が与えられる(大きさは 100 程度を想定しよう).
+ ''2'' から ''n-1'' のすべての整数までで,''n'' を割り切れるかどうか出力する.
+ 上の結果を用いて,''n'' が素数かどうか,出力する.

具体的には,''sample.rb'' というプログラムファイルだとして,例えば
//
>  ''ruby -w sample.rb 11''
<
と動かすと,

  11 is NOT divisable by 2.
  11 is NOT divisable by 3.
  11 is NOT divisable by 4.
  11 is NOT divisable by 5.
  11 is NOT divisable by 6.
  11 is NOT divisable by 7.
  11 is NOT divisable by 8.
  11 is NOT divisable by 9.
  11 is NOT divisable by 10.
  
  Answer: 11 is a prime number.

という出力が得られ,
//
>  ''ruby -w sample.rb 12''
<
と動かすと,

  12 is divisable by 2.
  12 is divisable by 3.
  12 is divisable by 4.
  12 is NOT divisable by 5.
  12 is divisable by 6.
  12 is NOT divisable by 7.
  12 is NOT divisable by 8.
  12 is NOT divisable by 9.
  12 is NOT divisable by 10.
  12 is NOT divisable by 11.
  
  Answer: 12 is NOT a prime number.

という出力が得られるようにしたいということである.

そして,この出力結果を(''n'' を100前後の数字にして与えて) ''output.dat'' というファイルに記録しておけ,ということになる.

&ref(/materials/warning.png); こういう,「単調な繰り返しで人間がやるとなるとつらすぎる」計算こそ,コンピュータの得意とするところだ.よく味わおう.
&ref(/materials/warning.png); こういう,「単調な繰り返しで人間がやるとなると辛すぎる」計算こそ,コンピュータの得意とするところだ.よく味わおう.

&br;&br;
* レポート [#x3113e51]

以下の課題について,あたうかぎり賢明な調査と考察と実行をし,

&size(18){''ExpMath1-Report-10''};

という題名をつけて e-mail にて教官にレポートとして提出せよ.なお,各自の

+ 所属(学部,学科)
+ 学籍番号
+ 学年
+ 氏名

を書くのを忘れないように.

&ref(/materials/warning.png); 自分のレポート作成ツールセットを記載せよ(もちろん,今回のレポートもそのツールセットを使って作成すること).


** レポート課題 [#eb1a6fe5]

+ 実習で出てきた練習問題に対しての,自分の解答プログラムと,その結果を示せ.
+ 1. のプログラムを「詳細に」解説せよ.


* about Icons, ClipArts [#t5576989]

For details, see [[&ref(/materials/JNorth_arrow-right-sm.png); this>materials]].

// ━┃┏┓┛┗┣┳┫┻╋


// コマンドライン入力は「行頭を > で始める」.
// コマンドライン出力は「行頭をブランクで始める」.

// 実習アイコン
// &ref(/materials/notes.png);

// 注意アイコン
// &ref(/materials/warning.png);

// Link アイコン
// &ref(/materials/JNorth_arrow-right-sm.png);

// OK アイコン
// &ref(/materials/OK.png);

// NG アイコン
// &ref(/materials/NG.png);

// サンプルアイコン
// &ref(/materials/Gnome-Preferences.png);

// 大文字での強調
// CENTER:&size(24){''ほげほげ''};

// 太文字 + 赤 での強調
// &color(red){''''};

// programu source 表記
// #highlighter(language=ruby,number=on,cache=on){{}}