(3)10/12の授業内容
- いろいろな繰り返し表現について
- コマンドラインとの情報のやりとり
情報検索の授業では、繰り返しを行う際、主にwhileを用いてきました。ただし繰り返し処理にはwhile以外にもいくつかの方法があります。様々な方法を理解して自在に扱えるようにしましょう。
一定回数繰り返す(times)
timesは整数に備わっているメソッドで、単純に一定回数繰り返す場合に用います。以下のどちらの方法で記述しても構いません(times.rb)。
#!/usr/koeki/bin/ruby 4.times { print "Hello\n" }
#!/usr/koeki/bin/ruby 4.times do print "Hello\n" end
irsv{学籍番号}%chmod +x times.rb ./times.rb Hello Hello Hello Hello
整数を数えながら繰り返す
1から10までの合計を出すことを考えてみましょう。これまではwhileを使って表現をしてきました。まずは前回のプログラムを再掲してみます(goukei.rb)。
#!/usr/koeki/bin/ruby goukei = 0 i = 1 while i <= 10 goukei += i i += 1 end printf ("goukeiの値は%dです\n",goukei)
このプログラムはiの初期値を1として、繰り返しを行うごとにiの値を1ずつ増加しながらgoukeiに加えていくというものです。そしてiが10を超えたら終了になりますので、結果的に1から10までの合計を出したことになります。
これはuptoメソッド、downtoメソッドを使って表現することも可能です。以下はuptoメソッドを用いて上記のプログラムを書き直したものです。goukei-upto.rbの名前をつけて保存し、実行してみましょう。
#!/usr/koeki/bin/ruby
goukei = 0
1.upto(10) do |i| #from.upto(to)。1から10までiを1ずつ増加させる。
goukei += i
end
printf ("goukeiの値は%dです\n",goukei)
同様にdowntoメソッドを用いて書き直すと下記のようになります。goukei-downto.rbの名前をつけて保存し、実行してみましょう。
#!/usr/koeki/bin/ruby
goukei = 0
10.downto(1) do |i| #from.downto(to)。10から1までiを1ずつ減少させる。
goukei += i
end
printf ("goukeiの値は%dです\n",goukei)
もうひとつ、連続した整数を繰り返すには、forと整数範囲を用いた以下の繰り返し表現も可能です
for 変数 in 整数範囲 繰り返して行う処理 end
これで1から10までの合計を記述すると以下のようになります。goukei-for.rbの名前をつけて実行してみましょう
#!/usr/koeki/bin/ruby
goukei = 0
for i in 1..10 #iに1から10まで順次代入する
goukei += i
end
printf ("goukeiの値は%dです\n",goukei)
飛び飛びに繰り返す
uptoやdowntoは1ずつ増加、減少させながら繰り返し処理を行うためのメソッドでした。では、10+20+30+、、、+100のように10ずつ増加する場合や、2+4+6+、、、+10のように2ずつ増加する場合はどうすればよいでしょうか。これについてもまずはwhileでの表現方法を見てみましょう
#!/usr/koeki/bin/ruby goukei = 0 i = 10 while i <= 100 goukei += i i += 10 end printf ("goukeiの値は%dです\n",goukei)
このようにiの初期値を10として、繰り返しを行う中で10ずつ増加させていけばうまくかけます。なお、一定間隔で値を変える方法として、stepメソッドもあります。stepメソッドの基本構造は下記の通りです。
開始値.step(終了値, 増加値) do |変数|#開始値から終了値まで変数を増加値ずつ増加させる
繰り返して行う処理
end
この中で増加値は省略することができます。省略された場合は増加値は1とみなされます。実際に10から100まで100ずつ増加させて加算してみましょう。goukei-step.rbの名前をつけて保存し実行してみましょう
#!/usr/koeki/bin/ruby goukei = 0 10.step(100, 10) do |i| goukei += i end printf ("goukeiの値は%dです\n",goukei)
増加値には負の値を入れることもできます。上記の足し算は100から初めて10ずつ減らしながら10までを全て足すと置き換えても同じ結果が出るはずです。goukei-step.rbを書き換えて、同じ結果になることを確認しましょう
変化の割合がばらばらな場合=配列の要素に対する繰り返し
では、1から10までのような連続した値でなく、10、20、30、、、のような変化の割合が一定でもない場合はどうしたらよいでしょうか? 例えば、2+8+9+12+20+25の場合を考えましょう。この場合、[2,8,9,12,20,25]という配列を想定し、配列内の要素を全て足すことを考えればよいということになります。配列内の要素の足し算もwhileで記述することができました。
#!/usr/koeki/bin/ruby
a = [2,8,9,12,20,25]
goukei = 0
i = 0
while i < a.length #.lengthは配列内の要素の数を返すメソッド
goukei += a[i]
i += 1
end
printf ("goukeiの値は%dです\n",goukei)
配列内の要素の加算はforを使って表現することもできます。下記は、配列の中の要素を順次変数に代入していくことをあらわしています。
for 変数 in 配列 上記の変数を使った処理 end
これを使って先ほどのwhileのプログラムを書き直してみましょう
#!/usr/koeki/bin/ruby
a = [2,8,9,12,20,25]
goukei = 0
for i in a #配列内の要素を順次iに代入する
goukei += i
end
printf ("goukeiの値は%dです\n",goukei)
ktermにおいてrubyプログラムを実行する際
irsv{学籍番号}%./prog.rb
とか
irsv{学籍番号}%ruby prog.rb
と入力しました。
プログラムを実行する際に
irsv{学籍番号}%ruby prog.rb 100, 200, 300
のようにプログラム自身に引数を与えると、プログラムを実行するときに利用することができます。与えた引数は自動的にARGVという配列変数に代入されます。
上記の例では
ARGV[0] = "100"
ARGV[1] = "200"
ARGV[2] = "300"
となっています。いずれも文字列であることに注意が必要です
これを利用すると、プログラムを起動する際に与えた情報に基づいて動作を決定させることができます。
例えば、1から10までuptoメソッドを使って合計を求めるgoukei-upto.rbを、1から指定した数までの合計を求めるプログラム(goukei-ARGV.rb)に書きかえることを考えましょう。例えば30までの合計を求める場合、実行する際に
irsv{学籍番号}%ruby goukei-ARGV.rb 30
と入力することになります。これを実行できるようにプログラムを改良すると下記の通りとなります(goukei-ARGV.rbという名前をつけて保存し、実行してみよう)。なお、goukei-upto.rbからの変更点を黄色で示します。
#!/usr/koeki/bin/ruby if ARGV[0] == nil STDERR.print "1からプログラム起動時に指定した値までの合計を出します\n" STDERR.print "50までの総和を出したい場合 ruby goukei-ARGV.rb 50と入力します\n" exit(1) end goukei = 0 goal = ARGV[0].to_i 1.upto(goal) do |i| goukei += i end printf ("1から%dまでの合計は%dです\n",goal, goukei)
新しく出てきた部分について説明します
if ARGV[0] == nil:nilはデータがないという意味。配列変数ARGVの0番目の値がない場合、つまりプログラムを起動する場合に引数を与えなかった場合は以下の処理を行いなさいという意味です
STDERR.printの2行:nilの場合に画面に表示するメッセージです。rubyプログラムは結果を画面に出力する変わりにファイルに出力することもできます。しかしこの2つのメッセージはいわばエラーメッセージですから、ファイルに出力されては困ります。単に出力するメソッドはprintですが、STDERR.printとすることにより、出力先がファイルに指定されていても、必ず画面に表示することが可能になります
exit(1):exitは直ちにプログラムの実行を終了しシステムに終了コードを返すための方法です。エラーが発生した場合などはプログラムを続けても意味がないのでexitを使用して終了させます。なお、プログラムの実行が終わった際、プログラム全体がうまくいったかどうかをシステムに対して教えることができ、これを終了ステータスと呼んでいます。終了ステータスは整数で表し、プログラムがうまくいったとき→0、うまくいかなかったとき→0以外とする決まりになっています。exit(1)としているのは、「予定した仕事ができずに終了してしまった」ことをシステムに伝えています。
goal = ARGV[0].to_i:goalという変数にプログラム起動時に入力された引数を代入しています。引数は文字列として扱われるため、.to_iをつけて整数に変換しています
1.upto(goal) do |i|:終了値を具体的な値ではなくgoal変数に変更しています。goal変数に代入されているのはプログラム起動時に指定した値です
printf ("1から%dまでの合計は%dです\n",goal, goukei):%dを2つに増やしています。これに伴い""の後の変数を2つにしています。
課題
以下のうちどれか1つを選んで解答してください。ただし、いずれの場合も
- while以外の繰り返し表現を利用する(while以外の方法はわからないが、whileを使えば書ける場合、whileでプログラムを作成してよい。この場合は採点結果−1点を得点とする)
- 「任意の自然数」はプログラムの起動時にコマンドラインから与える
ものとします。
問題1:1からはじめて任意の自然数までの奇数の積を求めるプログラムoddmul.rbを作成せよ(8点満点で採点)
問題2:指定した任意の自然数からはじめて、100までのその自然数の倍数を全て足した値を求めるaddsum.rbを作成せよ(9点満点で採点)
いずれも最後のprintfの行で積や和の値だけを表示した場合の採点基準です。1×3×5×、、、×X=XXXXXや、2+4+6+、、、Y=YYYYYのように式の形式で結果を出力することができた場合は、それぞれ満点を1点プラスして採点します(これはかなり難しいので無理に挑戦しなくても良いです)
作成したプログラムや実行結果をメールでnaoya@e.koeki-u.ac.jp宛に送る.
課題の提出期限は10月18日(火)23:59までです
メール送信時の注意
- Subjectは「学籍番号-1012」とすること
- 本文の1行目ではまず名乗ること
- 2行目以降は下記の構成で記載すること
- 作成したプログラム(メール本文に貼り付ける)
- プログラムの説明
- プログラムの実行結果
- 作成で苦労した点や感想
採点基準:期限内提出(2点)、プログラム(2点〜4点:何点満点で採点するかにより異なる)、説明(3点)、指示通りにメールを送っているか(1点)
説明の採点は、使用した繰り返し表現、ARGVについて説明がなされているか、満点が+1点になる結果出力方法を用いた場合は、うまく表示させるためにどのような工夫をしたかを詳しく書いているかどうかを中心に見る
途中までしかできない場合でも提出をすれば部分点を与えますので、未提出だけは避けましょう
Tips
emacsについて
- emacsで新しいファイルを作成する場合は,C-x C-fを押し,ミニバッファにkensaku/kadai2.rbのようにファイル名を入力する
- ファイルの保存はC-x C-s
- 日本語入力のオンオフの切り替えはC-o
Mewについて
- emacsを起動する
- Escとxを押し,mewと入力しReturn(Escとxを押すことを,一般にM-xと表記します)%<--これでMewが起動します
- Mewを起動するとパスワードがたずねられるので入力しReturn
- 新着メールの確認およびパスワードを間違えた場合はiと入力しReturn
- メールを読む場合は,カーソルキー(矢印キー)で読みたいメールを選びReturn
- メールの新規作成はwと入力
- e-mailの本文にテキストファイルを読み込むには,新規送信メール画面の本文を記入するエリアにカーソルを移動し,Ctrl+x,iとすると,ミニバッファにInsert file: ~/と表示されるので,読み込みたいファイル名を入力する。
- プログラムの実行結果の貼り付けは,kterm上の出力結果部分をマウスで選択し,Mewの本文の貼り付け位置にカーソルを移動し,マウスの真ん中ボタンをクリックする
- メールの送信はC-c C-cと入力するか,もしくはメニューのsendアイコンをクリックする
- Mewを終了するにはqと入力
- emacsを終了する