第3部>課題: P187(第14章)
第3部の課題は、練習で使ったファイル「ex1401.rb」に検索機能を追加するというもの。与えられた条件自体は、これまでの練習の応用レベルなので難しくありませんでしたが、意図しない箇所でErrorが発生してしまい若干ビビリました。
触っているうちになんとなくErrorの原因が予測できたので調べてみると、やはり原因はローカル変数のスコープでした。これ結構、Ruby入門者はハマる箇所じゃないのかな〜?別記事にて補足します。
別記事にて補足する予定だったローカル変数のスコープについて、m-kawatoさんのブログ「m-kawato@hatena_diary」に「これだ!」という記事がありましたので、リンクを張らせていただきました。私同様、Ruby入門者の方は一読をお薦めします。
- 作者: 久保秋真
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2012/11/26
- メディア: 単行本
- クリック: 4回
- この商品を含むブログ (3件) を見る
課題のプログラムは、まずranメソッドに選択肢とsearchBookInfosを追加してから、searchBookInfosの処理を書きました。「ex1401.rb」に追加した箇所は85行目以降です。
検索機能は、入力された検索条件検と全て一致した蔵書データの一覧を表示する仕様です。書籍名の比較だけ練習でパターンマッチを使ってみました。索機能って奥が深そうですね〜。色々と欲張って盛り込もうとしましたが、ハマる気配がしたのでやめておきました。もっと上手で綺麗なコードが書けるようになりたいです。頑張るぞ。
なお、Rubyのバージョンは1.9.3-p194です。
# coding: utf-8 require 'date' class BookInfo # Bookinfoクラスのインスタンスを初期化する def initialize( title, author, page, pdate ) @title = title @author = author @page = page @pdate = pdate # publish_date end # 最初に検討する属性に対するアクセサを提供する attr_accessor :title, :author, :page, :pdate # Bookinfoクラスのインスタンスの文字列表現を返す def to_s "#{@title}, #{@author}, #{@page}, #{@pdate}" end # 蔵書データを書式をつけて出力する操作を追加する # 項目の区切り文字を引数に指定することができる # 引数を省略した場合は改行を区切り文字にする def toFormattedString( sep = "\n" ) "書籍名: #{@title}#{sep}著者名: #{@author}#{sep}ページ数: #{@page}ページ#{sep}発刊日: #{@pdate}#{sep}" end end # BookInfoManagerクラスを定義する class BookInfoManager def initialize @book_infos = {} end # 蔵書データをセットアップする def setUp # 複数冊の蔵書データを登録する @book_infos["Yamada2005"] = BookInfo.new( "実践アジャイル ソフトウェア開発法とプロジェクト管理", "山田 正樹", 248, Date.new( 2005, 1, 25 ) ) @book_infos["Ooba2006"] = BookInfo.new( "入門LEGO MINDSTORMS NXT レゴブロックで作る動くロボット", "大庭 慎一郎", 164, Date.new( 2006, 12, 23 ) ) end # 蔵書データを登録する def addBookInfo # 蔵書データ1件分のインスタンスを作成する book_info = BookInfo.new( "", "", 0, Date.new ) # 登録するデータを項目ごとに入力する print "\n" print "キー: " key = gets.chomp print "書籍名: " book_info.title = gets.chomp print "著者名: " book_info.author = gets.chomp print "ページ数: " book_info.page = gets.chomp.to_i print "発刊年: " year = gets.chomp.to_i print "発刊月: " month = gets.chomp.to_i print "発刊日: " day = gets.chomp.to_i book_info.pdate = Date.new( year, month, day ) # 作成した蔵書データ1件分をハッシュに登録する @book_infos[key] = book_info end # 蔵書データの一覧を表示する def listAllBookInfos puts "\n------------------------------" @book_infos.each { |key, info| print info.toFormattedString puts "\n------------------------------" } end def searchBookInfos # 検索データ1件分のインスタンスを作成する book_info = BookInfo.new( "", "", 0, nil ) # 検索するデータを項目ごとに入力する print "\n" print "書籍名: " book_info.title = gets.chomp print "著者名: " book_info.author = gets.chomp print "ページ数: " book_info.page = gets.chomp.to_i print "発刊年: " year = gets.chomp.to_i print "発刊月: " month = gets.chomp.to_i print "発刊日: " day = gets.chomp.to_i if year > 0 && month > 0 && day > 0 book_info.pdate = Date.new( year, month, day ) end # 分かりやすい名前の変数に検索データを代入する search = book_info # 該当する蔵書データを格納するハッシュを作る found_book = {} # 蔵書データを1軒ずつ取り出して検索データ(条件)と比較する @book_infos.each { |key, info| search_flag = 1 # 検索条件と一致しているか input_check = 0 # 検索条件が未入力か if search.title != "" search_flag = 0 if search.title =~ /[^"#{info.title}"]/ else input_check += 1 end if search.author != "" search_flag = 0 if search.author != info.author else input_check += 1 end if search.page != 0 search_flag = 0 if search.page != info.page else input_check += 1 end if search.pdate != nil search_flag = 0 if search.pdate != info.pdate else input_check += 1 end # 比較が全て一致した蔵書データをハッシュに格納する # 検索条件が全て未入力の場合は格納しない found_book[key] = info if search_flag == 1 && input_check <4 } puts "\n------------------------------" if found_book.size > 0 # 比較が全て一致した蔵書データを表示する found_book.each { |key, info| print info.toFormattedString puts "\n------------------------------" } else print "条件に一致する蔵書はありません" puts "\n------------------------------" end end # 処理の選択と選択後の処理を繰り返す def run while true # 機能選択画面を表示する print " 1. 蔵書データの登録 2. 蔵書データの表示 3. 蔵書データの検索 9. 終了 番号を選んでください(1,2,3,9):" # 文字の入力を待つ num = gets.chomp case when '1' == num # 蔵書データの登録 addBookInfo when '2' == num # 蔵書データの表示 listAllBookInfos when '3' == num # 蔵書データの検索 searchBookInfos when '9' == num # アプリケーションの終了 break; else # 処理選択待ち画面に戻る end end end end # アプリケーションのインスタンスを作る book_info_manager = BookInfoManager.new # BookInfoManagerの蔵書データをセットアップする book_info_manager.setUp # BookInfoManagerの処理の選択と選択後の処理を繰り返す book_info_manager.run