roy > naoya > Rubyプログラムエラー対応

Rubyプログラムエラー対応

エラーを恐れる必要はない

Rubyプログラムを作成しktermで実行すると、思ったような結果が得られないことがある。プログラムが止まらなくなることもあれば、エラーメッセージが表示されて全く動かないこともある。

プログラム作成にエラーはつきものである。最初からエラーのないプログラムを作ることはほとんど不可能と言っても良い。エラーを修正しながら最終的に正しく動くプログラムを作ることができればよいのである。エラーを繰り返し経験することで、間違いやすい箇所も覚えることができるようになる。

ここでは典型的なエラーをいくつか取り上げ、エラーメッセージの読み方と、エラーが発生した際の対応方法を見ていく。

エラーメッセージの読み方

プログラムを実行したら次のエラーメッセージが表示されたとする。これはどのように読み取ればよいだろうか。

hoge.rb:5:in '+': String can't be coerced into Fixnum (TypeError)
       from hoge.rb:5
  • hoge.rb:実行したプログラム名
  • 5:エラーのある行数(5行目にエラーがある)
  • '+': String can't be coerced into Fixnum (TypeError):具体的なエラー内容

このエラーでは5行目にエラーがある。したがってemacsで作業中のプログラムの5行目を見ればよい。emacsではカーソルが何行目にあるか容易に確認できる。emacsの下部に以下の表示がある。このうちL12が行数をあらわす。これを見れば現在12行目にいることがわかる。

-かんな-U:--   hoge.rb      ALL  L12

エラーの例

プログラムの保存場所の間違い

sime{c11xxxx}% ruby hoge.rb[Return]
ruby: No such file or directory -- hoge.rb (LoadError)
  • No such file or directory:プログラムを保存した場所と実行している場所が違う。例えば、プログラムはrubyディレクトリの中に作成したが、ktermで実行する際にcd rubyをしてrubyディレクトリに移動していない場合。

変数の間違い(スペルミス等)

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

x = 100
p y
sime{c11xxxx}% ruby hoge.rb[Return]
hoge.rb:5: undefined local variable or method `y' 
for main:Object (NameError)
  • undefined local variable or method....:変数のスペルミスや指定間違い

4行目ではpメソッドで変数yの中味を表示させようとしているが、yは始めて登場する変数であり、何も代入されていないため表示することができずエラーになっている。この例は極端な間違いだが、変数名をnamesとするかわりにnameとするなどのスペルミスでも同じエラーメッセージが出る。

メソッドのスペルミス

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

x = 100
prinf("xは%dです\n",x)
sime{c11xxxx}% ruby hoge.rb[Return]
mistake.rb:5: undefined method `prinf' 
for main:Object (NoMethodError)
  • undefined method....:メソッドのスペルミス

引用符の閉じ忘れ

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

x = 100
printf("xは%dです\n,x)
sime{c11xxxx}% ruby hoge.rb[Return]
mistake.rb:5: unterminated string meets end of file
mistake.rb:5: parse error, unexpected $, expecting ')'
  • unterminated string meets end of file:引用符の閉じ忘れ

文法間違い

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

print "好きな数字を入力\n"
number = gets.chomp!.to_i
if number % 2 == 0
  print"偶数です\n"
else
  print"奇数です\n"
sime{c11xxxx}% ruby hoge.rb[Return]
./mistake.rb:10: parse error
  • parse error:文法間違い。ifやwhileに対するend忘れであることが多い。

エラーを防ぐためには

インデントを行う

while-end内やif-end内をインデント(字下げ)することでwhile文やif文がどこで始まりどこで終わっているかわかりやすくなる。これにより、記載する行の間違いやendのつけ忘れを防ぐことができる。念のため同一のプログラムを(1)インデントをした場合、(2)インデントをしない場合の2パターンで示す。(1)インデントをした場合の方が見やすいのは明らかである。

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

sum = 0

while true
  print"金額を入力してください(お会計は0と入力):\n "
  price = gets.chomp!.to_i
  if price == 0 then
    break
  end
  sum += price
end

printf("ありがとうございます。お会計 %d 円になります。\n", sum)
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

sum = 0

while true
print"金額を入力してください(お会計は0と入力):\n "
price = gets.chomp!.to_i
if price == 0
then break
end
sum += price
end

printf("ありがとうございます。お会計 %d 円になります。\n", sum)

もう少し長いプログラムを書くようになると、while文の中にwhile文が登場したり、さらにif文が登場したりして、endを複数使用するようになる。endがないとプログラムはうまく動かない。インデントをする習慣をつけるとendの抜け落ちに気づきやすくなる。

インデントを行う場合、スペースキーを何回か押しても良いが、Tabキーを押すと自動的に適切な位置にインデントをしてくれる。便利なので確認しておこう。

pメソッドによるデバッグ

プログラムに潜む誤り(バグ)を取り除く作業をデバッグという。デバッグを行う際は、プログラムの動きを頭の中で追いかけ、おかしい箇所を修正することになる。しかし、全て頭の中で追いかけるのはなかなか難しい。

そこで役に立つのがpメソッドである。pメソッドは変数に代入された値を表示することができる。これにより、予想通りに値が変数に代入されているかを確認しながら処理の流れを追いかけることができるため、間違いの絞込みが行いやすくなる。

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

x = []
y = 0
i = 0
while line = gets
  if /\S+\s+(\d+)\s+(\d+)/ =~ line
    x[i] = $1.to_i
    y += $2.to_i
    i += 1
    p x
  end
end

for j in x
  printf("%d\n", j)
end

printf("%d\n", y)

これはプログラムではwhile-end内にp xを入れている。xは配列であるため、pメソッドで表示することにより、配列への値の格納状況を確認することができる。しかし下の実行結果を見ると常に[]であり、配列への代入が行われていない。ここからは望ましい結果が得られない理由が、配列内の値の処理方法のまずさではなく、そもそもうまく代入が行われていないためであることがわかる。

sime{c11xxxx}% ruby hoge.rb[Return]
[]
[]
[]
[]