読者です 読者をやめる 読者になる 読者になる

ochalog

Ruby と MediaWiki が好きな電子・情報系の学生のブログ。

「情報科学入門 Rubyを使って学ぶ」の配布プログラムの不具合を発見した

プログラミング Ruby 情報科学入門

最近読み進めている「情報科学入門 Rubyを使って学ぶ」の配布プログラムに含まれている練習問題確認プログラム(check.rb)が Ruby 1.9.3-p327 でうまく動かないことが分かり、修正を行ったのでメモ。

報告したほうが良いだろうか。

問題と対策

invalid multibyte char エラーが出る

$ ruby check-old.rb ex04.rb
check-old.rb:56: invalid multibyte char (US-ASCII)

これは Ruby 1.9 の多言語化に対応していないため。マジックコメントで文字コードを伝えればよい。

# encoding: utf-8

定義した関数が「見つからない」

(上の問題を解決した後で)練習 4.1 で prime.rb というファイルに prime(n) という関数を定義するのだが、定義しても確認プログラムでは「見つからない」と表示される。

$ ruby check-old-enc.rb ex04.rb
 
 
 
======================================================================
 
 
 
テストデータファイルとして ex04.rb を使います...
ファイル prime.rb を読み込みます...
 
 Ex4.1      [対象のメソッド: prime           ] => ERROR: 対象のメソッドが見つかりません.

確認プログラムでは load("prime.rb") のようにファイル名を指定してファイルを読み込んでいるが、ライブラリに同名のものが存在しているとライブラリが優先して読み込まれてしまう(組み込み変数 $: でライブラリのパスがより上位に指定されているため)。今回の prime も標準添付ライブラリに含まれていたためライブラリが読み込まれてしまい、ライブラリに存在しない prime() 関数を呼び出したことでエラーが起きた。

対策としては、load("./prime.rb") のようにカレントディレクトリのファイルを明示的に指定して読み込むようにすればよい。これは check.rbtestreport(reportname, testcases) 関数に含まれているので、ここを修正して reportname"./" で始まっていないときに "./" を足すようにする。

def testreport(reportname,testcases)
  filename = %r(^\./) =~ reportname ? reportname : "./#{reportname}"
 
  # (中略)
 
  load(filename)
 
  # (以下略)

diff

修正前後のファイル(check-old.rbcheck.rb)の diff は以下のとおり。

$ diff -u check-old.rb check.rb

で出力。

--- check-old.rb 2012-12-21 13:12:18.023483587 +0900
+++ check.rb 2012-12-21 13:02:36.667477012 +0900
@@ -1,4 +1,4 @@
-#!/usr/bin/env ruby
+#encoding: utf-8
  
 # Usage:
 #   cm12345$ ruby ./check.rb [--report] test.rb
@@ -142,11 +142,13 @@
 end
  
 def testreport(reportname,testcases)
+  filename = %r(^\./) =~ reportname ? reportname : ("./" + reportname)
+
   jputs
-  jputs("ファイル " + reportname + " を読み込みます...")
+  jputs("ファイル " + filename + " を読み込みます...")
  
   begin
-    load(reportname)
+    load(filename)
   rescue LoadError => le
     # Case of "file is not found."