hiyoko-programingの日記

プログラミングを勉強したてのひよっ子。   エンジニア目指して勉強中。

デバッグの方法

デバッグ

デバッグとは、プログラム中の不具合を発見し、動作を正常にするまでの一連の作業のこと。

 

以前、ダウンロードしたファイルのうち、error_sample.rbをテキストエディタで開くと、こちらは、入力した数に対し1~100までの内で約数となっている数の個数を数えてくれるプログラムである。

実行すると入力待ちになり、そこで入力した数の約数を調べて表示する。

error_sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    show_divi(divi)
  end

  def self.show_divi
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

ここで、見慣れない文法が出てきた。上記の5行目の部分は、for文と呼ばれる構文。

for文

forは、「while」と同じく繰り返しに関する書き方。以下のように記述する。

for文の例
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
  for num in 1..10 do
    puts num
  end
  1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  => 1..10

上記の例では、変数numに1を代入して出力、2を代入して出力、3を・・・という処理を、10まで行なっている。1..10は、[1,2,3,4,5,6,7,8,9,10]と書くのと同じ。

inの後ろに書いたオブジェクトを順番にnumに入れて、endまでの処理を行う。

では、error_sample.rbを実行してみる。

 ~/error_question/error_sample.rbを実行。

 エラーが起こる操作である。

ターミナル
1
2
3
4
  $ cd ~/error_question
  # 実行したいファイルのあるディレクトリまで移動
  $ ruby error_sample.rb
  # ファイルを実行

すると、以下のようなエラーが出る。

ターミナル
1
2
  $ ruby ~/error_question/error_sample.rb
  /Users/koichiroabe/error_question/error_sample.rb:17: syntax error, unexpected end-of-input, expecting keyword_end

まずはエラー文を読む。エラー文とは、あるファイルが正常に実行されなかった際の原因を報告してくれる文。多くの場合、エラー文はターミナル上でファイルを実行した直後の行に出力される。

今回の場合のエラー文は以下の部分。

1
2
  /Users/koichiroabe/error_question/error_sample.rb:17: syntax error, unexpected end-of-input, expecting keyword_end
  # エラー文

エラー文には以下の2つの重要な情報が含まれている。

  1. どんな種類のエラーか

  2. ファイルの何行目でエラーが起きたか

1.に関して

今回は以下の部分がエラーの種類を示す。

syntax error, unexpected end-of-input, expecting keyword_end

syntax errorは文法に関するエラーだということ。unexpected end-of-input, expecting keyword_endは、構文を閉じるための<end>の数がおかしいことを示している。

2.に関して

Rubyは、エラー文においてエラーが起こっている場所をちゃんと教えてくれる。

error_sample.rb:17:、つまり、error_sample.rbの17行目でエラーが発生しているよ、ということ。しかし、今回のエラーは<end>の数によるものである。このエラーの場合、該当の行でエラーが起きているわけではない。Rubyが、endの必要な部分までコードを読んで、そこでエラーを検知するからである。ほとんどの場合はエラーが起こっている場所を正確に示しますが、そうでない場合もあるのでする。

以上の情報からわかることは、このファイルのどこかに<end>の足りない構文があるということ。

error_sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    show_divi(divi)
  end

  def self.show_divi
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

この中で<end>が必要な箇所は全部で5箇所ある。まず、一番大きなくくりであるclassとメソッドに関してみてみる。

インデントが揃えてあるので、どの<end>がクラスやメソッドに対応しているのかが明示的である。15行目がclassの閉じタグ、10行目と14行目がそれぞれのメソッドの閉じタグになっていることがわかる。

ここに関しては問題なく存在するようである。

続いて、クラスメソッド「find_divi」の中を見てみる。

find_divi
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    show_divi(divi)
  end

この中で<end>が必要な箇所は2箇所ある。for文と、if文である。

しかし、<end>は実際には1つしかない。どうやら、8行目と9行目の間に必要なfor文のための<end>が抜けていたようである。

こちらを修正し、もう一度プログラムを実行する。

 もう一度error_sample.rbを実行。

ターミナル
1
2
3
4
5
6
7
  $ pwd
  ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_sample.rb
  # ファイルを実行

  #任意の数字を入力

すると、またエラーが起こってしまう。

1
  $ error_sample.rb:13:in `show_divi': wrong number of arguments (1 for 0) (ArgumentError)

今度はどこが悪いのか。またエラー文を読むことで解決を試みる。

まず、エラーが起きた場所だが、今回は13行目だと書かれている。

次にエラーが起きた原因だが、wrong number of arguments (1 for 0)とある。

wrong number of arguments

wrong number of arguments とは、引数の数が違う、いう意味。(1 for 0)と後ろに書かれている場合、メソッドを呼ぶ際には1つの引数を渡しているのに、メソッドを定義している箇所では何も受け取っていないよ、という意味になる。

とりあえずエラー箇所である13行目を見てみると、一見普通にクラス定義がされているようである。

しかし、よく見ると間違いがあるのに気が付く。呼び出す箇所(10行目)では引数を書いているのに、13行目の関数定義には引数を受け取る記述がない。

error_sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi
  # => 変数diviを受け取っていない!
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

これでは、14行目で変数diviを出力できない。

というわけで、13行目を修正する。

error_sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

これで、正常に動くようになったはず。再度ファイルを実行。

ターミナル
1
2
3
4
5
6
7
8
9
  $ pwd
  ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_sample.rb
  # ファイルを実行

  4
  #任意の数字を入力(ここでは4にしています)
  #数字が出力されていれば成功

 

ここで、このプログラムがどう動くのかをひと通りさらってみる。

【1行目~16行目まで】

error_sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

まず、1行目から16行目まででclassとそのクラス・メソッドを定義して、ここまでは定義を読み込むだけである。

【17行目】

error_sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

pという変数に対して、右辺のgets.to_iの値を代入している。

getsメソッドによる入力待ちになるが、ここでは「4」と入力したことにする。

【18行目】

error_sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

ErrorSampleクラスのクラス・メソッドであるfind_diviメソッドが呼ばれている。この時、引数として17行目で定義したpを利用している。処理の流れは呼び先であるfind_diviメソッドの定義されている3行目に移動する。

【3行目】

error_sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

3行目末尾にある(p)は、18行目から引数として渡されてきた変数pをfind_diviメソッドの内部では「p」として扱うという宣言になる。つまり、ここでは17行目で定義したpをpとしてそのまま利用できる。

【4行目】

sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

数字の0を、変数diviに代入する。

【5行目 〜 9行目】

sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

for文の中身に入っていく。このfor文では9行目までの処理が100回、繰り返される。6行目にあるif文では、pでnumを割って余りが0になったらtrueになるので、pの約数の際に変数diviの数が1増える。つまりdiviは1〜100までの間にあるpの約数の数になる。

【10行目】

sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

10行目では、13行目に定義されているクラスメソッドshow_diviを呼び出している。その際、変数diviを引数として利用し、処理は13行目に移る。

【13〜14行目】

sample.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class ErrorSample

  def self.find_divi(p)
    divi = 0
    for num in 1..100 do
      if p % num == 0
        divi = divi + 1
      end
    end
    show_divi(divi)
  end

  def self.show_divi(divi)
    puts divi
  end
end
p = gets.to_i
ErrorSample.find_divi(p)

13行目末尾で渡された変数diviをdiviとして扱うという宣言をしている。そして、14行目のputsメソッドでdiviの値を出力してプログラムが終了する。

今回pには4を代入した。すると、約数diviは3になるはずなので、3と出力される。

問題

ダウンロードしたerror_questionフォルダの中にあるerror_question1.rb ~ error_question8.rbを実行すると、すべてエラーが起こる。先ほどのデバッグの例を参考にコードを修正し、プログラムを正常に動作させる。

以下にそれぞれのファイルが正常に動作した場合の挙動と、エラーの解決法を解説したリンクを記す。

error_question1.rb

正常な動作

ターミナル
1
2
3
4
5
6
7
  $ pwd
  /Users/ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_question1.rb
  # ファイルを実行
  Member: tanaka, suzuki, satoh
  #上記が出力されていれば成功

解答解説

error_question1解答解説

エラー
1
2
3
4
$ ruby error_question1.rb
#ファイルの実行
error_question1.rb:7: syntax error, unexpected tCONSTANT, expecting keyword_end
#エラー文

原因

5行目の閉じ「"」忘れ

修正箇所

5行目末尾に「"」を追加する

error_question1.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def myoji

  name1 = "tanaka"
  name2 = "suzuki"
  name3 = "satoh"
  puts "Member: #{name1}, #{name2}, #{name3}"

end

myoji

解説

syntax error, unexpected tCONSTANT, expecting keyword_end

こちらのエラーは、閉じタグが無いことが原因で起こることが圧倒的に多いエラー。今回の場合、該当ファイルを開くと色が変わっている。色が変わっている部分の前後をよく見ると、文字列の定義で利用する「"」が一つ足りないことに気づける。

error_question2.rb

正常な動作

ターミナル
1
2
3
4
5
6
7
  $ pwd
  /Users/ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_question2.rb
  # ファイルを実行
  48
  #上記が出力されていれば成功

解答解説

error_question2解答解説

エラー
1
2
3
4
$ ruby error_question2.rb
#ファイルの実行
syntax error, unexpected end-of-input, expecting keyword_end
#エラー文

原因

9行目のwhile文に対応するendが無い

修正箇所

12行目にendを追加する。

error_question2.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def looper(a_sum, a_num1, a_num2)
  n = 4
  while n > 0
    a_sum += a_num1
    n -= 1
    m = 2
    while m > 0
      a_sum += a_num2
      m -= 1
    end
  end
  puts a_sum
end

sum = 0
num1 = 10
num2 = 1
looper(sum, num1, num2)

解説

syntax error, unexpected end-of-input, expecting keyword_end

オーソドックスなend忘れのエラー。このエラーを起こさないためには、endを必要とする構文を書く際は必ず最初にendを書いてしまってからその中身を書くと良い。

 

error_question3.rb

正常な動作

ターミナル
1
2
3
4
5
6
7
  $ pwd
  /Users/ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_question3.rb
  # ファイルを実行
  直径が4,高さが10の円柱の体積は120です
  #上記が出力されていれば成功

解答解説

error_question3解答解説

エラー
1
2
3
4
$ ruby error_question3.rb
#ファイルの実行
error_question3.rb:6:in `<main>': undefined local variable or method `diametar' for main:Object (NameError)
#エラー文

原因

5行目の変数名が間違っている

修正箇所

5行目の変数名を修正

error_question3.rb
1
2
3
4
5
6
7
8
9
PI = 3
diameter = 4
height = 10

radius = diameter / 2
circle_s = radius * radius * PI
column_v = circle_s * height

puts "直径が#{diameter},高さが#{height}の円柱の体積は#{column_v}です"

解説

undefined local variable or method 'diametar' for main:Object (NameError)

エラーの最後に(NameError)とある。これは、変数名などが間違っていることを示唆している。実際に間違っている箇所まで教えてくれるかは場合によってまちまちだが、エラーの可能性として誤字脱字もあることは念頭に置いておく。

error_question4.rb

正常な動作

ターミナル
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
  $ pwd
  /Users/ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_question4.rb
  # ファイルを実行
  0か1を入力してください
  #入力を促される
  0
  #数字の入力
  あなたの入力した数字は0です
  あなたの入力した数字は1です
  あなたの入力した数字は0でも1でもありません
  #入力した数字に応じて上記のいずれかが出力されていれば成功

解答解説

error_question4解答解説

エラー
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ ruby error_question4.rb
#ファイルの実行
0か1を入力してください
#0を入力
0
あなたの入力した数字は0です
error_question4.rb:5:in `ret': undefined method `elseif' for main:Object (NoMethodError)
#結果
0か1を入力してください
1
#1を入力
あなたの入力した数字は0でも1でもありません
#結果

原因

5行目、elsifとすべきところをelseifとしてしまっている

修正箇所

elseif → elsif

error_question4.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
  def ret(a_input)
    if a_input == 0
      puts "あなたの入力した数字は0です"
    elsif a_input == 1
      puts "あなたの入力した数字は1です"
    else
      puts "あなたの入力した数字は0でも1でもありません"
    end
  end

  puts "0か1を入力してください"
  input = gets.to_i
  ret(input)

解説

undefined method 'elseif' for main:Object (NoMethodError)

構文の中の文法を間違えていると、NoMethodErrorが出ることが多い。elsifは特に間違いやすいので、注意。

error_question5.rb

正常な動作

ターミナル
1
2
3
4
5
6
7
8
  $ pwd
  /Users/ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_question5.rb
  # ファイルを実行
  合計点は210です
  平均点は70です
  #上記が出力されていれば成功

解答解説

error_question5解答解説

エラー
1
2
3
4
$ ruby error_question5.rb
#ファイルの実行
error_question5.rb:4:in `+': String can't be coerced into Fixnum (TypeError)
#エラー文

原因

hashのscoreというキーのバリューの数字が文字列型になっており、4行目のsum = sum + a_score[:score]のところで数字+文字列の計算になっている

修正箇所

hash内の文字列オブジェクトで置かれている数字を、数字オブジェクトに変更。
または、数字の計算の時に文字列オブジェクトを数字オブジェクトに変換。

解答例1

error_question5.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def cal(a_scorebox)
  sum = 0
  a_scorebox.each do |a_score|
    sum = sum + a_score[:score]
  end
  puts "合計点は#{sum}です"
  ave = sum / a_scorebox.length
  puts "平均点は#{ave}です"
end

scorebox = []
scorebox << {name: 'tanaka', score: 90}
scorebox << {name: 'suzuki', score: 70}
scorebox << {name: 'satoh', score: 50}
cal(scorebox)

解答例2

error_question5.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def cal(a_scorebox)
  sum = 0
  a_scorebox.each do |a_score|
    sum = sum + a_score[:score].to_i
  end
  puts "合計点は#{sum}です"
  ave = sum / a_scorebox.length
  puts "平均点は#{ave}です"
end

scorebox = []
scorebox << {name: 'tanaka', score: '90'}
scorebox << {name: 'suzuki', score: '70'}
scorebox << {name: 'satoh', score: '50'}
cal(scorebox)

解説

error_question5.rb:4:in '+': String can't be coerced into Fixnum (TypeError)

こちらのエラーも、プログラミングを始めて間もないころには起こしがちである。しかし、エラー文をよく読めば何が間違っているのかわかりやすいエラーの一つでもある。

error_question6.rb

正常な動作

ターミナル
1
2
3
4
5
6
7
  $ pwd
  /Users/ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_question6.rb
  # ファイルを実行
  合計は28 平均は5
  #上記が出力されていれば成功

解答解説

error_question6解答解説

エラー
1
2
3
4
$ ruby error_question6.rb
#ファイルの実行
error_question6.rb:3:in `block in sum_ave': undefined method `+' for nil:NilClass
#エラー文

原因

定義していないsumという変数を利用しようとしている

修正箇所

sum_aveメソッドの中で、変数sumを定義する

error_question6.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def sum_ave(a_ary)
  sum = 0
  a_ary.each do |num|
    sum += num
  end
  ave = sum / a_ary.length
  puts "合計は#{sum} 平均は#{ave}"
end

ary = [5,8,3,10,2]
sum_ave(ary)

解説

undefined method '+' for nil:NilClass

実は、+もメソッドの一種である。

for nil:NilClassというエラーが出た場合、すぐに該当するレシーバー(メソッドを呼んだオブジェクト)の状態を確かめる。レシーバーがnilになってしまっている可能性が非常に高い。

error_question7.rb

正常な動作

ターミナル
1
2
3
4
5
6
7
  $ pwd
  /Users/ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_question7.rb
  # ファイルを実行
  10
  #上記が出力されていれば成功

解答解説

error_question7解答解説

エラー
1
2
3
4
$ ruby error_question7.rb
#ファイルの実行
error_question7.rb:6:in `+': nil can't be coerced into Fixnum (TypeError)
#エラー文

原因

ary[i]がnilになり、数字にnilを足そうとしている

修正箇所

5行目を「while <= 3」に変更

error_question7.rb
1
2
3
4
5
6
7
8
9
ary = [1,2,3,4]

sum = 0
i = 0
while i <= 3 do
  sum += ary[i]
  i += 1
end
puts sum

解説

nil can't be coerced into Fixnum (TypeError)

今回のエラーは、エラー文だけではなかなか気が付きづらいので、まずはどこでこのエラーが起こっているか把握する。そのために、pというメソッドを利用する。

pメソッド

pメソッドはputsメソッドと似ている。自身の右に書かれたインスタンスに関する出力するが、putsメソッドが返り値を出力するのに対し、pメソッドはそのままの形で出力する。以下に配列オブジェクトをそれぞれのメソッドで出力した例を示す。

【例】

putsとpの違い
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
  $ irb
  #irbの起動
  irb(main):001:0> ary = [1, 2, 3, 4]
  #出力する配列オブジェクトの定義
  irb(main):002:0> puts ary
  1
  2
  3
  4
  => nil
  #putsメソッドで出力
  irb(main):004:0> p ary
  [1, 2, 3, 4]
  => [1, 2, 3, 4]
  #pメソッドで出力

putsで配列オブジェクトを出力すると中身のオブジェクトを順番に1行ずつ出力する。対してpの場合は、そのオブジェクトの形のまま出力されているのがわかる。

変数の形がどうなっているのかを確かめたい場合は、pメソッドを利用すると良い。

このpメソッドを、問題のコードの以下の部分に挿入する。

error_question7.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
ary = [1,2,3,4]

sum = 0
i = 0
while i <= 4 do
  p ary[i]
  sum += ary[i]
  i += 1
end
puts sum

そしてもう一度実行すると、以下のような実行結果になる。

error_question7.rb
1
2
3
4
5
6
1
2
3
4
nil
error_question7.rb:7:in `+': nil can't be coerced into Fixnum (TypeError)

5行目から始まるwhileの繰り返しの中にpメソッドが入っているので、繰り返しの回数分出力が行われている。これによりわかることは、whileの繰り返し中にある6行目の出力のうち、5回目がnilになっているということである。

配列オブジェクトに格納された要素の取り出し方は、1番目なら[0], 2番目なら[1],
というように、取り出したい順番 - 1の数字を[]に入れる。また、この問題のコードでは、while文の中でiという変数の数字が増えていき、そのiをary[i - 1]として配列の中身を取り出すことに利用している。そして、iは1~4の値を取る。するとiが4になった瞬間、配列オブジェクトaryから5番目の要素を取得する、という意味になり、配列オブジェクトaryには5番目の要素が無いためにおかしなことになっているということのようである。

ここで新たに得た重要な知識としては、配列の中から存在しない順番のインスタンスを取得しようとするとその値はnilになるということ。

原因がわかったので、配列から要素を取り出す際に利用する部分を修正する。配列の1番目の要素が取得できるように、iにははじめ0を代入しておく。そして、whileの繰り返しの条件も「iが3以下の時」に変更する。

これで、望む結果が得られるはず。デバッグ用に書いた6行目を消すことを忘れないようにする。

error_question8.rb

正常な動作

ターミナル
1
2
3
4
5
6
7
  $ pwd
  /Users/ユーザー名/error_question
  # 現在error_questionディレクトリに居ることを確認
  $ ruby error_question8.rb
  # ファイルを実行
  合計は10です
  #上記が出力されていれば成功

解答解説

error_question8解答解説

エラー
1
2
3
4
$ ruby error_question8.rb
#ファイルの実行
error_question8.rb:1:in `cal': wrong number of arguments (2 for 4) (ArgumentError)
#エラー文

原因

1行目の引数の数と、8行目の引数の数が一致しない

修正箇所

error_question8.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def cal(a_num1, a_num2, a_num3, a_num4)
  sum = a_num1 + a_num2 + a_num3 + a_num4
  return sum
end

num1 = 1
num2 = 2
num3 = 3
num4 = 4
sum = cal(num1, num2, num3, num4)
puts "合計は#{sum}です"

解説

wrong number of arguments (2 for 4) (ArgumentError)

メソッドを呼び出している部分の引数と、メソッドを定義している部分の引数の数は必ず一致していなければいけない。(2 for 4)というのは、メソッドが4つの引数を求めているのに2つしか渡せていないですよ、という意味になる。