情報科学概論
2002.5-21
出席に関する注意事項を説明しますので,その注意を良く聞いてから,電子メールにより出席の申告をしてください.「件名」は
gairon 5-21 attend s0240**
のように自分の学生番号を使って下さい.なお,入力ミスがあると出席として認
められないことになりますので,慎重に行ってください.文
字はすべて1バイト文字 (半角英数字) です.途中に入るスペースは一度に一個だけと
してください.スペースは全部で3個です.また,**の部分は自分の学生番号の下二桁
です.
計算機によるプログラミングにおいて,繰り返しは重要なポイントです.人間が
嫌いな単純作業の繰り返しも,計算機は文句一つ言わずに延々と実行してくれます.スマー
トな処理も良いですが、繰り返しを使うと,簡単にプログラミングできるケース
がありますし、ファイルなどを読み込んでその内容を整形したり、変更したりす
る処理も,テキストデータを繰り返し読み込んで処理をする繰り返しを応用して
います.ここでは,基本的な繰り返しを実行する for 文について学習
します.
n = ARGV[0].to_i sum = 0 for i in 1..n do sum += i end puts sum |
上のスクリプトの動作は、1からコマンドライン引数として読み込んだ整数まで の和を求めるものですが、1からその整数である n まで,ただひたす ら変数 sum に自己代入しているものです.その繰り返しを行っている のが、for から end までの部分で,仮においた変数 i を使って、 i が1から n に なるまで, do 以下の処理を行う命令です.
ここで, do は省略可能です.1..n と言う部分が、1から n までを表しますが、ここで, もし,1...n のようにピリオドを一つ増や すと1から n-1 までになります.sum は初め、0が代入されていますが、ループの中で そのときの i の値を足されていきます.す なわち,一回目の処理で1が加えられ、2回目の処理で 2が加えられ,...というものです.これにより、和が 求まります.
注意しなければならないのは、for ループの中で定義した変数はルー プの外では使用できないことです.このように、定義された変数が使える範囲を 「スコープ」と言います.上の例で、ループが始まる前に sum の値を 初期化しているのはそのためです.
処理の流れを図1に示します.このような図をフローチャート(流れ図)と言いま す.ループの終了は実は前回述べた if のような処理をしていますが、 for ... end の組が自動的に処理してくれ ます.
図1 for ループにおける処理の流れ
では,1から奇数 n までの奇数の和はどうでしょうか.
n = ARGV[0].to_i odd_sum = 0 for i in 1..(n+1)/2 do odd_sum += 2 * i - 1 end puts odd_sum |
少し変りましたが、形は同じです.1から奇数 n まで,奇数は (n+1)/2 個あるので,そこまでの奇数を足すだけです.奇数は一般的に 2n -1 と書けます.ここで,n は整数です.
次の例は偶数の和です.
n = ARGV[0].to_i even_sum = 0 for i in 1..n/2 even_sum += 2 * i end puts even_sum |
処理はもう分かるでしょう.
コマンドライン引数の平均値を求めるスクリプトも以前に宿題で出しました.そ のときは、引数の個数を4個に限定しましたが、何個あるか分からない場合でも 処理できます.また,ここでは,ARGVの配列もそのまま利用します.
sum = 0 n = ARGV.size for i in 1..n sum += ARGV[i-1].to_f end puts sum / n |
ここで,新しいメソッドである size が出てきました.これは,オブ ジェクトのサイズを返すメソッドです.次のような例を実行してみて,感じをつ かんでください.
a = 1 b = [1,2,3] c = "abcdefg" puts a.size puts b.size puts c.size |
この結果は,次のようになります.
$ ruby size.rb = = = = = = = = 4 3 7 |
変数の b と c の結果は分かりやすいものです.b については,配列の要素の個数を返しています. また,c では文字の個数を返しています. しかし,a の結果は分かりづらいものでしょ う.これは,Rubyが内部で処理している「バイト数」 を表しています.今のところは意味が分からなくても 構いません.
引数を配列に代入していくのは数値だけとは限りません.
str = [] for i in 0...ARGV.size str[i] = ARGV[i] end p str |
について,たとえば、
$ ruby str.rb apple orange lemon
などとして結果を見てください.
また,処理を行う範囲を配列で指定することもできます.次の処理は配列の要素 を順次表示していくスクリプトです.
for i in [2,3,5,10] print i, "\n" end |
これまで,ARGV という定数を何度か使用してきました.これは、コマ ンドラインから引数として与えられた文字列を要素とする配列でした.ここでは、 それと似ている ARGF についても使ってみましょう.これは,コマン ドライン引数として与えられたファイル名に対してその中身を扱うものです.次 のスクリプトを試してみましょう.
for i in ARGF print i end |
これを,cat.rb という名前で保存し、カレントディレクトリに先ほどの str.rb があるとして次の ように実行してみてください.
$ ruby cat.rb str.rb
このスクリプトはターミナルでファイルの中身を見るのに使用する cat と同じ働きをします.
配列との組合わせの例の最後として少し実用的なものを紹介しましょう.ここで は,「剰余モード」を利用します.剰余モードとは整数を整数で割ったときの余 りを利用するものです.方法はいくつかありますが、ここでは、次のようなもの を使用します.
puts ARGV[0].to_i % ARGV[1].to_i |
この使い方は
$ ruby div.rb 8 3
のように引数を二つとって実行すると、前の整数を後ろの整数で割った余りを表 示してくれます.これを応用して、以下のようなものを作ってみました.
month = [0,31,28,31,30,31,30,31,31,30,31,30] day = ["月曜日","火曜日","水曜日","木曜日","金曜日","土曜日","日曜日"] a = 0 for i in 0..ARGV[0].to_i-1 a += month[i] end print "その日は ", day[(a + ARGV[1].to_i) % 7], " です\n" |
動作については、自分で考えてみましょう.
これまで,スクリプトの実行のために,ruby というコマンドを使用し てきました.しかし,ターミナルでコマンドとして実行できるようにする方法も あります.その場合には、ファイルの先頭に次のようなおまじないを入れておい てください.
#!/usr/bin/ruby |
そうしたあとで、スクリプトファイルの属性に「実行権限」を与えます.スクリ プトが存在するディレクトリで、
$ chmod +x hoge.rb
のように,ファイル名を指定して chmod コマンドにより実行権限を与 えます.chmod については、「基礎講座」テキストのp.90を参考にし てください.さらに便利に利用するには、自分の script ディレクト リに「コマンドパス」を通しておくのが良いでしょう.次の設定を行って おけば,ls や cd などの普通のコマンドと同じように自分 の作ったスクリプトを実行できます.
まず,ホームディレクトリにある .bash_profile というファイルをエ ディタで開きます.次に、その最後に以下の行を加えておきます.
export PATH=$PATH:$HOME/script/ |
これにより,スクリプト名がコマンドとしてどのディレクトリからも実行可能に なります.環境変数である PATH については、「基礎講座」教科書の p.131からの説明を参考にしてください.
上記の内容について,特に,for 文の使い方につ いて実習してください.自分で様々に変型したスクリプトをつくって試すのが良 いでしょう.
授業の終りに宿題 (AクラスとBクラス別々) について説明しますので,アナウンスに注意してください.