#acl benevolent0505:admin,read,write,revert,delete Known:read,write All:read #format gfm # Rubyの基本的な文法 この回ではRubyの基本的な文法をやっていきます。言語はRubyを使いますが、ここでやる内容のほとんどは他のプログラミング言語でも共通することです。ですので、他の言語をやってみたことがある人は、その言語と比較しながらやってみるといいでしょう。 ## 前回のプログラムの解説 前回の文字を表示するプログラムについて解説します ```ruby puts "Hello, world!" ``` ### オブジェクト まずは後ろの`"Hello, world!"`の部分に注目します。この部分を`Stringオブジェクト`または`文字列オブジェクト`、あるいは単に`文字列`と呼んだりします。Rubyでオブジェクトとはデータや、それについての処理を表現する基本的な単位のことを言います。Rubyでは文字列や数値などの様々なデータがオブジェクトになります。ここでの`"Hello, world!"`は「Hello, world!」という文字列を表わすオブジェクトということになります。オブジェクトについては後々詳しく触れていくので、今すぐに理解する必要はありません。今は呼び方だけ慣れておきましょう。 ### メソッド 次に`puts`の部分に注目します。`puts`というのは「画面に文字の列を表示する(画面に文字列を出力する)」という **メソッド** です。メソッドという言葉も後々詳しく解説しますが、ここでは「プログラムで処理をする単位」というように覚えておけばいいでしょう。 今まで`puts 表示したい文字列`のように書いてきましたが、実はこれは本来の書き方を省略した形になります。省略せずに書くと ```ruby puts("Hello, world!") # Hello, world! ``` のようにメソッド名の後ろに`()`を付けます。この`()`の省略は打ち込む文字数が減って便利ですが、やりすぎると読みにくいプログラムになってしまうので気をつけましょう。 さて、`puts`は`()`の中にある文字列や数値を出力します。これは`puts`というメソッドに表示させたいオブジェクトを与えるという形になります。この後ろに与えるオブジェクトのことを **(メソッドの)引数** といいます。ここでは`"Hello, world!"`が`putsメソッド`の`引数`になります。 またメソッドによっては引数が無いものもあります。 ### 文字列 文字列についてもう少し解説をしておきます。文字列オブジェクトはダブルクォーテーションマーク`""`かシングルクォーテーションマーク`''`で囲んで作成することができます。 なので次の2つ`puts`は同じものを出力します。 ```ruby puts "Hello, world!" # Hello, world! puts 'Hello, world!' # Hello, world! ``` さて、`"Hello, "benevolent0505"!"`という文字列を表示したくなったとします。ではやってみましょう。どのようになるでしょうか。 ``` irb(main):010:0> puts "Hello, "benevolent0505"!" SyntaxError: (irb):10: syntax error, unexpected tIDENTIFIER, expecting end-of-input puts "Hello, "benevolent0505"!" ^ from /Users/Mikio/.rbenv/versions/2.2.3/bin/irb:11:in `
' irb(main):011:0> ``` なにやら見慣れぬ表示が出てきました。 `SyntaxError` とは正しくRubyのプログラムを入力しなかったときに出るエラーメッセージです。 ここでは、`"Hello, "`で一区切りされているのに、`benevolent0505`というRubyにとってよくわからないものが現れたのでエラーが出たのです。 では`""`の中で`"`を使うためにはどうすればいいのでしょうか。`"`の前にバックスラッシュ`\`の記号を付けてやってみましょう。(環境によっては¥記号で表示されます) ```ruby puts "Hello, \"benevolent0505\"!" # Hello, "benevolent0505"! ``` 今度は思った通りに表示されました。このようにRubyにとって特別な記号を表示するには記号の前に`\`の記号を付けると表示されます。他にもRubyにとって特別な役割を持つ特殊文字が存在します。詳しくは下のリファレンスマニュアルを見てみるといいでしょう。 さて、さっきの`puts "Hello, \"benevolent0505\"!"`の`"`の囲みを`'`に変えてみるとどうなるでしょう。 ```ruby puts 'Hello, \"benevolent0505\"!' # Hello, \"benevolent0505\"! ``` 今度は`\`や`"`がそのまま表示されてしまいました。このように`''`で囲んだ文字列は中身の特殊文字を解釈しません。 参考: [Ruby 2.3.0 リファレンスマニュアル > リテラル > バックスラッシュ記法](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fliteral.html) ### p, printメソッド 文字を表示するメソッドについてもう2つ紹介しておきます。 一つは`printメソッド`です。putsメソッドでは文字列を表示した後で改行を行っていましたが、printメソッドでは文字列の最後に改行を行わないません。実際に試してみましょう。 ```ruby print "Hello, world!" ``` ``` Hello, world!=> nil ``` printメソッドは表示の最後で改行を行いたくないときに使うと便利です。 もう一つは`pメソッド`はirb上で使うと便利なメソッドです。試しに下のプログラムをirb上で動かしてみましょう。 ```ruby puts "100" # 100 puts 100 # 100 p "100" # "100" p 100 # 100 ``` putsやprintメソッドでは`"100"`も`100`も表示されるときには同じ`100`と表示されてしまいます。これでは *数値* の100か *数字* の100かわかりません。pメソッドはオブジェクトによって表示の仕方を変えてくれるので、このように数値や数字の違いを意識したいときなどに使うと便利です。 ## 変数 今までのプログラムでは文字を表示するときや計算をするときには、`"Hello, world!"`や`1`などの値をそのまま扱ってきました。このままでもプログラムを組むことはできますが、何度も同じ文字列を表示させたり、沢山の値を使って計算させるときには不便です。 こうした不便を解決してくれるもので **変数** というものがあります。変数とはそれぞれの値に名前を付けるようなイメージです。 変数の作り方は下の様に`変数名 = 値`というように書きます。これを「変数名に値を代入する」と言います。 ``` 変数名 = 値 ``` ```ruby mma_id = "benevolent0505" student_number = "1410000" puts mma_id puts student_number ``` ### 予約語 変数名にはどんな文字列を使ってもいいですが、変数に使えない文字列というものがあります。これを **予約語** といって、これらは既にRubyのプログラミング言語を作る上で使用されている文字列なので、それを上書きするようなことは出来ません。 ``` BEGIN class ensure nil self when END def false not super while alias defined? for or then yield and do if redo true __LINE__ begin else in rescue undef __FILE__ break elsif module retry unless __ENCODING__ case end next return until ``` 試しに予約語に値を代入してみようとすると ``` irb(main):001:0> __LINE__ = "Hello" SyntaxError: (irb):1: Can't assign to __LINE__ __LINE__ = "Hello" ^ from /Users/Mikio/.rbenv/versions/2.2.3/bin/irb:11:in `
' irb(main):002:0> ``` このようにエラーが出ます。 参考: [Ruby 2.3.0 リファレンスマニュアル > 字句構造 > 予約語](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2flexical.html) ## 式 **式** とは簡単に言ってしまえば「評価をして値を返すもの」のことです。評価するとはその式がどんな値になるのかを言います。 次に書いたものはRubyでは全部式になります。 ``` irb(main):010:0> message = "Hello, world!" # 変数への代入も式 => "Hello, world!" ← これ irb(main):011:0> message # 変数自体も式 => "Hello, world!" irb(main):012:0> "Hello, world!" # 具体的な値も式 => "Hello, world!" ← これ irb(main):013:0> 1 # ↑と同じ => 1 ← これ irb(main):014:0> 1 + 1 # 計算式も式 => 2 ← これ irb(main):015:0> ``` また返される値のことを **返り値 (戻り値)** と言います。今までirbでプログラムを実行していたときに`=>`の後に`nil`などの表示が出てきていたと思います。これが返り値です。 参考: [Ruby 2.3.0 リファレンスマニュアル > プログラム・文・式](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fprogram.html) ### 式展開 `puts 変数名`という形で書くと、その変数の値が表示されることをやりました。さて、プログラムを書いていると、文字列と変数の値を組み合せて表示したいときがあります。文字列と変数の値を組み合せて表示する方法は後で説明する`+`の演算子式を使うやり方と、ここで説明する **式展開** があります。 ```ruby mma_id = "benevolent0505" student_number = "1410000" puts "Hello, #{mma_id}" # "Hello, benevolent0505" puts "Your student number is #{student_number}" # Your student number is 1410000 puts 'Hello, #{mma_id}' # Hello, #{mma_id} ``` ダブルクォートで`""`で囲まれた文字列の中では`#{}`の中の式を評価することができます。これを使うことで文字列と変数の値を組み合わせることができます。式展開を使うことができるのはダブルクォートで囲まれた文字列だけなので、シングルクォート`''`で囲まれた文字列では評価されません。 式展開は文字列中で式を評価するので、文字列の中でRubyのプログラムを実行させることができます。 ```ruby puts "1 + 1 = #{1 + 1}" # 2 ``` 参考: [Ruby 2.3.0 リファレンスマニュアル > リテラル > 式展開](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fliteral.html#exp) ## 演算子式 今まで変数の作成や計算などで使っていた`=, +, -, *, /, %`などの記号のことを **演算子** と呼びます。 ```ruby puts 1 + 1 # 2 puts 5 - 3 # 2 puts 5 * 5 # 25 puts 10 / 3 # 3 puts 10 % 3 # 1 ``` 上で紹介しているものは算術演算子と呼ばれるもので、Rubyには他にも論理演算子や範囲演算子などがあります。演算子については次回改めて説明をします。 Rubyでは`+`の演算子を使って、文字列を連結することができます。 ```ruby puts "Hello, " + "world!" # Hello, world! ``` また、`*`の演算子を使って文字列をその数だけ表示することもできます。 ```ruby puts "Hello!" * 3 # Hello!Hello!Hello! ``` 演算子には優先順位があります。算術演算子において、`()`が先で`*, /`がその次などの計算の優先順位は普通の数学と同じになります。 ```ruby (1 + 10) * 10 / 2 > 55 ``` ### 自己代入 例えば変数`count`を使っていて`count`に`1`を足した値を代入したいとします。そのときは例えば`count = count + 1`というように書くことができます。しかし`count`を2回書かないといけないため若干面倒です。そこでRubyでは`count += 1`のように書くこともできます。これを自己代入といいます。 ```ruby count = count + 1 count += 1 ``` 算術演算子での自己代入の例を下に示しておきます。 | 自己代入 | 意味 | |:------:|:---------:| | a += 2 | a = a + 2 | | a -= 2 | a = a - 2 | | a *= 2 | a = a * 2 | | a /= 2 | a = a / 2 | 参考: [Ruby 2.3.0 リファレンスマニュアル > 演算子式](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2foperator.html) ## 数値オブジェクトとStringオブジェクト 今まで数値と文字列を扱ってきましたが、あまり詳しくは触れてきませんでした。ここでは数値オブジェクトとStringオブジェクトについて見ていきます。 ### 数値オブジェクト Rubyでは整数同士の計算では、その返り値も整数になります。また浮動小数点数(小数)同士の計算では、その返り値も浮動小数点数になります。では整数と浮動小数点数の計算ではどうなるでしょうか。戻り値は浮動小数点数になります。 ```ruby 1 + 1 # 2 2.5 + 1.0 # 3.5 1.5 + 1 # 2.5 0.0 + 1 # 1.0 ``` 数値のあとに`.to_f`や`.to_i`を付けることで整数を浮動小数点数にした値を返したり、逆に浮動小数点数を整数にした値を返します。 ```ruby 10.to_f # 10.0 10.1.to_i # 10 10.9.to_i # 10 ``` 他にもRubyには有理数や複素数を表すオブジェクトがあります。 参考: [Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Numericクラス](http://docs.ruby-lang.org/ja/2.3.0/class/Numeric.html) ### Stringオブジェクト 今まで文字列は単発で表示させてきましたが、それぞれを連結することができます。文字列同士を連結するには`+`の記号を使います。 ```ruby message = "Hello" mma_id = "benevolent0505" puts message + ' ' + mma_id # Hello benevolent0505 ``` ここでは`Hello`と` `と`benevolent0505`が連結されたものが表示されています。このようにして文字列を連結することができます。 さて、数字の`'1'`と数字の`'2'`を足すとどうなるでしょうか。`'1' + '2'`の戻り値は`'12'`になります。これは文字列の`'1'`と文字列の`'2'`を連結したために`'12'`という結果になったのです。 ```ruby '1' + '2' # 12 ``` 文字列の数字を数値にして扱いたいときは、文字列の後に`.to_i`や`.to_f`を付けると文字列の数字を整数や浮動小数点数にした値を返します。 ```ruby '1'.to_i # 1 '1'.to_f # 1.0 ``` またプログラムを書いているときに文字列の長さが知りたいときがあります。そのときは文字列の後ろに`.size`を付けることで、その文字列の長さの数値を返します。 ```ruby "ruby-lang".size # 9 str = "ruby-lang" str.size # 9 ``` 参考:[Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Stringクラス](http://docs.ruby-lang.org/ja/2.3.0/class/String.html) ここで紹介した`to_i`や`to_f`,`size`はみなそれぞれのオブジェクトの持つ *メソッド* です。オブジェクトはデータや、それについての処理を表現するものだと書きました。このそれぞれのデータについての処理がメソッドなのです。 ## 制御構造 今までのプログラムは上にかかれたものから1行ずつ順番に実行していくものでした。しかし、実際に作りたいプログラムはこれでは中々表現することができません。プログラムでは条件に応じて特定の処理を行いたかったり、同じ処理を何度も繰り返したかったりします。これを **制御構造** と言います。制御構造には次の4つがあります。 * 条件分岐 * 繰り返し * 例外処理 ここでは上の条件分岐と繰り返しを取扱います。 ## 条件分岐 プログラムを書いていると、特定の条件に応じて処理を分けたいことがあります。例えばテストの点数に応じて表示するメッセージを変えたかったり、学年によって履修出来る授業の表示を変えたかったりといったりです。 こうした条件に応じて処理を分岐させることを **条件分岐** と言います。 ### 真偽値 真を表現する`true`と偽を表現する`false`があります。 ### 比較演算子式 比較演算子式は、オブジェクト同士を比較してその結果を`true/false`で返します。比較演算子式には以下のようなものがあります。数学で使っているような記号が多いですが、`==`,`!=`,`>=`,`<=`などの記号は見なれていないと思うので気を付けましょう。 ```ruby 2 == 2 # true 1 == 2 # false 2 != 2 # false 1 != 2 # true 3 > 1 # true 3 > 3 # false 3 >= 3 # true 3 < 1 # false 3 < 3 # false 3 <= 3 # true ``` ### 論理演算子式 論理演算子式は複数の条件を1つにまとめることができます。 ```ruby true && true # かつ true true && false # かつ false true || true # または true true || false # または true false || false # または false !true # 否定 false !false # true ``` 例えば、`変数xが1以上かつ100以下の整数`という条件は次のようになります。 ```ruby x = 80 x >= 1 && x <= 100 # true ``` また`&&`,`||`,`!`はそれぞれ`and`, `or`, `not`を使うことができます。 ```ruby x >= 1 and x <= 100 # true ``` ### if式 Rubyで条件分岐を行うものとして`if式`があります。`if式`は次のように書きます。 ```ruby if 条件式 条件式が成立している時に実行したいこと end ``` これにより`math_point`が`60`点以上のときに`合格です`と表示するプログラムを書くときには ```ruby math_point = 70 if math_point >= 60 puts "合格です" end ``` というふうに書くことができます。 条件が成立していない場合にも処理を行いたいときがあります。 ```ruby if 条件式 条件式が成立している時に実行したいこと else 条件式が成立していない時に実行したいこと end ``` ある条件が成立していないときに、次の条件について調べたいときもあります。 ```ruby if 条件式1 条件式1が成立している時に実行したいこと elsif 条件式2 条件式1が成立しておらず、条件式2が成立している時に実行したいこと elsif 条件式3 条件式1,2が成立しておらず、条件式3が成立している時に実行したいこと else 条件式1,2,3が成立していない時に実行したいこと end ``` これらのことを使って`math_point`の値によって成績の表示を変えるプログラムを書いてみると次のようになります。 ```ruby math_point = 70 if math_point >= 90 puts "秀" elsif math_point >= 80 puts "優" elsif math_point >= 70 puts "良" elsif math_point >= 60 puts "可" else puts "不可" end ``` またRubyにおいて`if`は **式** なので値を返します。if式の返す値は実行された条件の最後の式を評価した値が返り値になります。 ```ruby message = if max_point == 100 "満点です" end puts message # "満点です" ``` 条件式が成立しない場合は`nil`が返ってきます。nilとはオブジェクトが存在しないことを指す特別な値です。 ```ruby message = if 0 == 1 "not return" end message # => nil ``` ### if修飾子 Rubyではある1行を条件に応じて実行したいときは次のように書くこともできます。条件が成立しない場合は実行されません。 ```ruby math_point = 60 puts "合格です" if math_point >= 60 puts "not execute" if math_point < 60 ``` ### 条件演算子式 条件演算子式はとても便利な演算子です。他の言語では三項演算子などと呼ばれていたりします。 ```ruby a = 1 b = 2 max = 0 if a < b max = b else max = a end puts max ``` これまでやったことでこのプログラムは`a < b`という条件式の真偽値によって`max = b`か`max = a`が評価されるとわかるでしょう。しかし、行っていることを考えてみると結構単純で、慣れてくるとこれだけのことにわざわざこれだけのことを書くのが面倒になってきます。 このプログラムを一行で書けるようになるのが条件演算子式です。書き方は`条件式 ? 成立しているときの式 : 成立していないときの式`と書き、上のプログラムは次のようになります。 ```ruby # こう書ける max = a < b ? b : a puts max ``` 条件演算子式はとても便利でプログラムがすっきりしますが、複雑な条件分岐をやるのには適していません。使う場面には注意が必要です。 ここでは紹介しませんでしたが、他にも`unless`や`case`の条件分岐の式があります。詳しくはリファレンスマニュアルを見てみるといいでしょう。 参考: [Ruby 2.3.0 リファレンスマニュアル > 制御構造 > 条件分岐](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fcontrol.html) ## 繰り返し Rubyで繰り返しの処理を行う方法はいくつかあります。ここでは`while`, `for`や`each`メソッドを使った繰り返しを説明します。 ### 配列 繰り返しについてやる前に、 **配列** というものについて触れておきます。配列とはいくつかのデータを順に並べたものです。配列もオブジェクトで、配列オブジェクトやArrayオブジェクトと呼ばれたりします。 配列の中のデータのことを普通は **(配列の)要素** と呼んだりします。配列の作り方は`[]`で囲んだものの中に要素をカンマ`,`で区切りで書いていきます。 ```ruby numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] colors = ["red", "blue", "green", "orange", "pink", "light blue", "purple"] # 別々の種類のオブジェクトを一つの配列に格納することも出来る mix = ["one", 2, "three", 4, 5] ``` 配列の要素を取得するためには`配列名[要素の位置]`で要素の値を返すことができます。 ```ruby puts numbers[0] # 1 puts numbers[3] # 4 puts colors[0] # "red" puts colors[8] # nil puts mix[-1] # 5 ``` また`配列名[要素の位置]`に値を代入することができます。 ```ruby arr = [] # 中身が空の配列ができる arr[0] = 'M' # "M" arr[1] = 'M' # "M" arr[2] = 'A' # "A" p arr # ["M", "M", "A"] arr[4] = "outside" # 範囲外の位置にアクセスすると p arr # ["M", "M", "A", nil, "outside"] その位置に値が格納されて、間はnilで埋める ``` 配列の大きさが知りたいときには`size`メソッドを使います。 ```ruby puts numbers.size # 10 puts colors.size # 7 ``` #### 文字列オブジェクトと配列 文字列の一文字一文字を格納した配列がほしいときがあります。そのような場合には`chars`メソッドを使います。charsメソッドは文字列の各文字列を格納した配列を返します。 ```ruby p "Hello, world!".chars # ["H", "e", "l", "l", "o", ",", " ", "w", "o", "r", "l", "d", "!"] ``` 参考: [Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Stringクラス > chars](http://docs.ruby-lang.org/ja/2.3.0/method/String/i/chars.html) #### putsメソッドと配列について putsメソッドは引数が配列の場合、その要素と改行を順に出力します。配列を配列の形のまま表示したかったら、pメソッドか文字列に式展開で埋め込むのがいいでしょう。 ``` > puts numbers 1 2 3 4 5 6 7 8 9 10 => nil ``` 参考: [Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Kernelモジュール > puts](http://docs.ruby-lang.org/ja/2.3.0/method/Kernel/m/puts.html) ### 範囲オブジェクト Rubyには範囲を表すオブジェクトがあります。これを **範囲オブジェクト** といい次のように表します。 ```ruby puts 1..10 # 1 から 10 を表すオブジェクト puts 1...10 # 1 から 9 を表すオブジェクト ``` ここでの`..`と`...`は **範囲演算子式** といい、`..`の演算子式の左側に置かれたものから右側に置かれたもの以下の範囲オブジェクトを返します。`...`の演算子式は左側に置かれたものから右側に置かれたものまでの範囲オブジェクトを返します。 また当然数値を直接書かずに変数に入れたものでも大丈夫です。 ```ruby a = 5 b = 20 puts a..b ``` 範囲オブジェクトから配列を返す`to_a`というメソッドがあります。これは範囲オブジェクトの示す範囲の値を含んだ配列を返して、例えば`(1..10)`は`[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]`という配列を返します。 ```ruby p (1..10).to_a # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ``` 参考: [Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Rangeクラス](http://docs.ruby-lang.org/ja/2.3.0/class/Range.html) ### while式 ここからは繰り返し処理を行う式やメソッドについて紹介していきます。 `while式`は条件式が成立している間に、処理を行うものです。while式は次のように書きます。 ```ruby while 条件式 do 繰り返したい処理 end ``` `do`は省略して書くことができます。 ```ruby while 条件式 繰り返したい処理 end ``` 例えばwhileを使って配列の中身を全て表示するプログラムはこのように書けます。 ```ruby i = 0 while i < numbers.size puts numbers[i] i += 1 end ``` 実行結果 ``` 1 2 3 4 5 6 7 8 9 10 => nil ``` 参考: [Ruby 2.3.0 リファレンスマニュアル > 制御構造 > while](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fcontrol.html#while) ### for式 繰り返しを行う式として`for式`もあります。書き方は次の通りです。この`do`も省略することができます。 ```ruby for 変数 in 繰り返したい配列or範囲オブジェクト do 繰り返したい処理 end ``` `for`は配列や範囲オブジェクトについての繰り返し処理を行う式です。`変数`には配列や範囲オブジェクトの値が順々に代入されていきます。 ```ruby for i in 1..5 # iには1, 2, 3, 4, 5と繰り返しのたびに範囲オブジェクトの値が代入されていく puts i end ``` 実行結果 ``` 1 2 3 4 5 => 1..5 ``` ```ruby for i in colors # iには"red", "blue", "green", ...とcolors配列の値が代入されていく puts i end ``` 実行結果 ``` red blue green orange pink light blue purple => ["red", "blue", "green", "orange", "pink", "light blue", "purple"] ``` 参考: [Ruby 2.3.0 リファレンスマニュアル > 制御構造 > for](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fcontrol.html#for) ### break 繰り返し中処理の途中で処理をから抜けたい(終わりたい)場合があります。そのような場合には`break`を使います。 ```ruby i = 0 while i < colors.size puts colors[i] if colors[i].size > 5 break end end ``` 実行結果 ``` red blue green => nil ``` 参考 [Ruby 2.3.0 リファレンスマニュアル > 制御構造 > break](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fcontrol.html#break) ### eachメソッド 配列や範囲オブジェクトには、要素の一つずつにアクセスできる`each`というメソッドがあります。書き方は次の通りです。 ```ruby (配列or範囲オブジェクト).each do |変数| 繰り返したい処理 end # こうも書ける (配列or範囲オブジェクト).each { |変数| 繰り返したい処理 } ``` eachは配列や範囲オブジェクトのメソッドなので、`配列.each`と書きます。`変数`には配列や範囲オブジェクトの値が順々に代入されていきます。 ```ruby numbers.each do |item| puts item # itemには1, 2, 3, 4, ...と繰り返しのたびに配列numbersの値が代入されていく end ``` 実行結果 ``` 1 2 3 4 5 6 7 8 9 10 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ``` 参考: [Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Arrayクラス > each](http://docs.ruby-lang.org/ja/2.3.0/method/Array/i/each.html) 参考: [Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Rangeクラス > each](http://docs.ruby-lang.org/ja/2.3.0/method/Range/i/each.html) #### for式とeachメソッドの違い forとeachの違いについて述べておきます。forとeachは式とメソッドという違いがありますが、処理は **ほぼ** 同じことをします。例えば、次の2つのプログラムは ```ruby for i in 1..3 puts i end ``` ```ruby (1..3).each do |i| puts i end ``` ``` 1 2 3 => 1..3 ``` この実行結果はどちらも上のようになります。では次は繰り返し処理をした後に変数の`i`をforやeachの繰り返しの外で表示してみましょう。irbで動かす場合は先にeachメソッドの例から実行してみてください。 ```ruby for i in 1..3 puts i end puts i ``` ``` 1 2 3 => 1..3 > puts i 3 => nil ``` ```ruby (1..3).each do |i| puts i end puts i ``` ``` 1 2 3 => 1..3 > puts i NameError: undefined local variable or method `i' for main:Object from (irb):2 from /Users/Mikio/.rbenv/versions/2.2.3/bin/irb:11:in `
' ``` eachを実行した後に変数`i`を表示しようとしたらエラーが出てしまいました。このエラーは変数などが作られていない(宣言されていない)ときに、その変数を参照しようとして出るエラーです。一方forの後で`i`を表示した場合は`3`が出てきました。forとeachの違いはこの始めに宣言する変数が繰り返し処理の外でも使えるのか、中でも使えるのかが違います。この違いは後に詳しく説明します。 #### 色々な繰り返しの方法について Rubyには繰り返しの方法はここに紹介した以外にもあります。極端なことを言えば、whileだけがあれば繰り返し処理を行う分には十分です。しかし、whileは条件式だけでしか繰り返しの開始と終了を表現できないですが、forやeachは配列の要素に対して繰り返し処理を行うことができます。配列についての繰り返しはforやeachが向いていることが多いですが、ある条件が成立している間ずっと繰り返し処理をしてほしいときはwhileの方が向いていることが多いです。 このように、繰り返しの場面によって向き不向きが出てきます。どんな場合でも同じ式やメソッドを使うのではなく、場面を考えて使い分けることが大切になります。 ### injectメソッド ```ruby puts numbers.inject(0) { |result, item| result + item} # 55 # 次に書くプログラムと同じ意味 result = 0 numbers.each do |item| result += item end puts result # 55 ``` 参考: [Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Enumerableモジュール > inject](http://docs.ruby-lang.org/ja/2.3.0/class/Enumerable.html#I_INJECT) 参考: [Ruby 2.3.0 リファレンスマニュアル > 制御構造 > 繰り返し](http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fcontrol.html) ## 値を入力する 今まではプログラムの中で宣言された数値や文字列の値を使ってプログラムしていきました。しかし、実際のプログラムではプログラム外からの *入力* を受け取ってプログラムを実行していくものがほとんどです。ここでは2種類の値を入力する方法を説明します。 ### コマンドライン引数 ARGV ターミナルから`ruby プログラム名.rb`というプログラムを起動するときに、このプログラムに引数を渡すことができます。この引数のことを **コマンドライン引数** と呼びます。 コマンドライン引数の渡し方は ``` > ruby プログラム名.rb 引数1 引数2 ... ``` という形で、ファイル名の後にスペース` `をあけて指定します。 Rubyのプログラムからコマンドライン引数を取得する方法は`ARGV`配列を使います。`ARGV`にはコマンドライン引数の値が渡された順に配列になって格納されています。ですので次のようなコマンドライン引数を渡したときは ``` ruby display.rb 1 2 3 4 5 6 7 8 9 10 ``` このようになります。 ```ruby p ARGV # ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] value1 = ARGV[0] # "1" value2 = ARGV[1] # "2" value3 = ARGV[2] # "3" ``` またコマンドライン引数で取得できる値は *文字列オブジェクト* なので、数値を取得したいと思った場合は`to_i`や`to_f`メソッドを使って取得する必要があります。 ### getsメソッド `gets`メソッドは一行読み込んで、読み込みに成功した時にはその文字列を返します。 ```ruby > message = gets hello, world # ←打ち込んだ文字列 => "hello, world\n" ``` ここで`gets`メソッドの返り値を見てみましょう。打ち込んだ文字列以外の文字`\n`が見えます。これは **改行文字** と呼ばれるものです。改行文字始めの方で述べた特殊文字の一つで、文字通り改行を表す文字です。 ``` irb(main):043:0> puts "Hello\nworld" Hello world => nil irb(main):044:0> ``` では何故改行文字が追加されてしまうのでしょうか。`gets`メソッドは一行読み込んでその文字列を返します。ここで一行の終わりを示すために`Enterキー(Return)`を入力しました。この`Enterキー(Return)`によって改行文字が入力されたのです。 この改行文字を取り除くには`chomp`というメソッドを使います。`chomp`は文字列の改行文字を取り除きます。 ```ruby > message = gets.chomp hello, world => "hello, world" ``` これにより、標準入力から文字列を取得できます。 参考: [Ruby 2.3.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > IOクラス > gets](http://docs.ruby-lang.org/ja/2.3.0/method/IO/i/gets.html) # エラーについて ここではよく見るエラーとその原因として考えられること、またその取り除き方を紹介します。まず次のプログラムを見てください。 `error.rb` ```ruby 1 arr = [-43, 61, 24, -49, -25, 59, -13, 8, 48, 58] 3 4 arr.each do |item| 5 puts itme # ここにスペルミスがある 6 end 7 ``` このプログラムは4行目で変数のスペルミスがあるので、正常に動かずエラーが出ます。 `実行結果` ``` error.rb:5:in `block in
': undefined local variable or method `itme' for main:Object (NameError) from error.rb:4:in `each' from error.rb:4:in `
' ``` このエラーを見てみましょう。エラーの始めに`error.rb:5`と書いてあります。ここはエラーが起こった行を指しています。現実にはここで表示される行がエラーの直接の原因でないこともあるのですが、原因を探る手掛かりにはなります。 次に```undefined local variable or method `itme' for main:Object (NameError)```という部分を見てみましょう。この部分を読むと、どういうエラーが発生しているのかがわかります。`undefined local variable or method ``itme' for main:Object`と書いてあるので「itmeという(ローカル)変数かメソッドが定義されていません」という意味です(このくらいの英語は読もう)。後に続く`(NameError)`はエラーの名前を表示しています。 このようにプログラム上の誤りを **バグ** といい、それを取り除くことを **デバッグ** といいます。デバッグを行うときに大切なことは、**原因をきちんと追求すること** です。よくエラーが出たときにいきなり書いたプログラムを消したり書き直す人がいますが、それはよくありません。プログラムを間違えたときは必ずエラーが出るので、それを見て何がエラーの原因だったのか、 **どうやったら二度とこの間違いを起こさないのかを考えて、再発防止の対策を打つまでがデバッグです。** 以下ではよく見るエラーを紹介していきます。 ## syntax error 文字通り文法上のエラー。よくあるミスとしては * `if`などの対応する`end`や`{}`の対応を書き忘れ * `(), {}, []`や`"", ''`がちゃんと閉じられていない * 演算子式は正しく使われているか などがあるので、このエラーに遭遇したときはこのような内容を確認してみるといいでしょう。 ## NameError / NoMethodError 変数やメソッド名が宣言されてなかった時のエラー。よくあるミスは * 変数名やメソッド名のスペルミス * 変数が宣言されていない * 変数の代入が正しく行われていない などがあります。 ## ArgumentError メソッドの引数に誤りがあったときのエラー。メソッドの引数の数を確認してみましょう。 # 演習問題 各実行例を参考にして、プログラムを作ってみてください。 ## 基本 * 3つの数を入力させて、それを足し算した結果を表示するプログラム ``` > ruby input_three_num.rb 1 2 3 a = 1, b = 3, c = 3 a + b + c = 6 > ``` * 文字列と整数を入力させて、文字列を指定された整数回繰りかえして表示するプログラム ``` > ruby repeat_str.rb Hello,world! 3 Hello,world! Hello,world! Hello,world! > ``` * 西暦の値が与えられた時、閏年かどうかを判定するプログラム。閏年の条件は次の3つになります。 1. 西暦年が4で割り切れる年は閏年 2. 西暦年が100で割り切れる年は平年(閏年ではない) 3. 西暦年が400で割り切れる年は閏年 参考: [閏年 wikipedia](https://ja.wikipedia.org/wiki/%E9%96%8F%E5%B9%B4) ``` > ruby leap_year.rb 2020 2020 is leap year. > ruby leap_year.rb 2019 2019 is common year. ``` * 渡された数値の配列の最大値を取得するプログラム(渡す配列の中身はなんでもいいですが、要素は一つ以上にしてください) ``` > ruby max.rb Array is [16, 71, 15, 99, 73, 66, 24, 3, 72, 83] Max number is 99. ``` * 数値の配列の平均を求めるプログラム ``` > ruby average.rb Array is [41, 95, 56, 15, 98, 6, 85, 61, 1, 78] Average is 53.6 ``` * 2つの数値を変数に格納し、その変数の中身を入れ変えるプログラム ``` > ruby swap.rb 12 41 before swap a = 12 b = 41 after swap a = 41 b = 12 ``` * 数値の配列が与えられた時、それを逆順に出力するプログラム ``` > ruby arr_reverse.rb Array: [97, 32, 3, 74, 6, 77, 71, 33, 72, 79] size: 10 Reversed: [79, 72, 33, 71, 77, 6, 74, 3, 32, 97] ``` * 文字列を引数にとって、それをひっくり返したものを戻り値とするメソッド ``` > ruby str_reverse.rb "No lemon, No melon" input str is No lemon, No melon reversed str is nolem oN ,nomel oN ``` * BMIを計算して太りすぎか痩せ過ぎかを判定するプログラム。BMIの計算方法は`BMI = 体重(kg) / 身長(m)^2`です。 また太りすぎか痩せ過ぎかの判定は次の基準で行うことにします。 | | | |:----------:|:---------:| | 低体重(痩せ型) | 18.5未満 | | 普通体重 | 18.5以上、25未満 | | 肥満(1度) | 25以上、30未満 | | 肥満(2度) | 30以上、35未満 | | 肥満(3度) | 35以上、40未満 | | 肥満(4度) | 40以上 | ``` > ruby bmi.rb 56 1.6 あなたのBMIは21.87 普通体重です ``` * 数値を与えられたら1からその数値までの数値を表示するプログラムを作ってください。ただし、3の倍数になったら`Fizz`、5の倍数になったら`Buzz`、3と5の倍数になったら`FizzBuzz`と表示させてください。 ``` > ruby fizzbuzz.rb 15 1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz ``` * 数当てゲーム 自分が思い浮べた数値を推測するプログラム。例えば`70`を思い浮べたときは ``` > ruby guess_number.rb guess number 1 ~ 100 Do you choose 50? Type bigger, smaller or yes...: bigger Do you choose 75? Type bigger, smaller or yes...: smaller Do you choose 62? Type bigger, smaller or yes...: bigger Do you choose 68? Type bigger, smaller or yes...: bigger Do you choose 71? Type bigger, smaller or yes...: smaller Do you choose 69? Type bigger, smaller or yes...: bigger Do you choose 70? Type bigger, smaller or yes...: yes Fufu! ``` というように実行される。 ## 発展(?) * 素数を見つける(エラトステネスの篩) * 最大公約数(ユークリッドの互除法) * ズンドコキヨシ * ハノイの塔