講評: if 文で、先に key があるのかどうか調べないと、 データになかった人間を登録してしまうことになります。 4 のトライアルは良かったです。 ただし、* -- end の文の行がそろっていないので、 作った本人ですら分かりにくいコードになっているようです。 標準入力、標準出力、ファイル入力をもう一度確かめておいて 下さい。 ---- 10 月 10 日 第 2 回レポート 「Hash 配列」 学籍番号:C106XXXX 氏名: XXXXXXXX 語学クラス:XXXX語XX 系:XXXX系 <前回の復習> Q.elsif とは A.条件を付け加えたい場合に、elsif を使う。 # if もしも A であるならば # B をせよ # elsif そうでなくてもし C ならば # D をせよ # end A でも C でもない場合は、何も実行されない。 1.公益大弓道部のメンバーの特徴を hash 配列 fighter とした。 fighter の key と value はそれぞれメンバーの名前とチャームポイントになる、 眼鏡の色をとりました。 その 1:key 「志賀」に対して value 「紺色メガネ」 その 2:key 「小林」に対して value 「青色メガネ」 その 3:key 「熊谷」に対して value 「黒色メガネ」 その 4:key 「公昭」に対して value 「グレーのメガネ」 その 5:key 「山田」に対して value 「新しいメガネ」 その 6:key 「ひでぷー」に対して value 「年季入ったメガネ」 記法その 1 ["志賀"] = ["紺色メガネ"] ["小林"] = ["青色メガネ"] ["熊谷"] = ["黒色メガネ"] ["公昭"] = ["グレーのメガネ"] ["山田"] = ["新しいメガネ"] ["ひでぷー"] = ["年季入ったメガネ"] 記法その 2 {"志賀" => "紺色メガネ", "小林" => "青色メガネ", "熊谷" => "黒色メガネ", "公昭" => "グレーのメガネ", "山田" => "新しいメガネ", "ひでぷー" => "年 季入ったメガネ"} 注意書き。いろいろ考えた結果 6 対になりました。お許し下さい。 2.計算問題。 A. 0d 1022 = 0x ?? 10 進数を 2 進数に直した後、16 進数に直して答えを出す。 まず、 10 進数を 2 進数に直す。 1022 ÷ 2 = 511 511 ÷ 2 = 255 … 1 255 ÷ 2 = 127 … 1 127 ÷ 2 = 63 … 1 63 ÷ 2 = 31 … 1 31 ÷ 2 = 15 … 1 15 ÷ 2 = 7 … 1 7 ÷ 2 = 3 … 1 3 ÷ 2 = 1 …1 よって、0d 1022 = 0b 1111111110 次に 2 進数を 16進数に直す。4 桁ごと右から区切り、16進数の表を見ながら、 当てはめていく。 0b11 = 3 、1111 = f 、1110 = e よって、0b 1111111110 = 0x 3fe ですから、0d 1022 = 0x 3fe B. 0d 1022 = 0b ?? さらに 16 進法に変換してみよ。 A の問題同様。10 進数を 2 進数に直して計算。 1022 ÷ 2 = 511 511 ÷ 2 = 255 … 1 255 ÷ 2 = 127 … 1 127 ÷ 2 = 63 … 1 63 ÷ 2 = 31 … 1 31 ÷ 2 = 15 … 1 15 ÷ 2 = 7 … 1 7 ÷ 2 = 3 … 1 3 ÷ 2 = 1 …1 よって、0d 1022 = 0b 1111111110 次に 2 進数を 16進数に直す。4 桁ごと右から区切り、16進数の表を見ながら、 当てはめていく。 0b11 = 3 、1111 = f 、1110 = e よって、0b 1111111110 = 0x 3fe ですから、0d 1022 = 0x 3fe よって、答えは同じになる。 ちなみに、参照した 16進数の表はこちら。 http://roy/~madoka/2007/r1/04/04-12-binary2.html 3.「key といえば value である」と表示するようにせよ。また、工夫できる点 を思いついた場合、どのように工夫したか述べ、適宜発表せよ。 a.あらかじめプログラムに登録してある対を表示するもの fighter.rb b.作成したプログラム #!/usr/koeki/bin/ruby $KCODE = 'e' # 日本語コード EUC で出力する fighter = Hash.new # Hash 配列を fighter と定義する fighter["志賀"] = "紺色メガネ" fighter["小林"] = "青色メガネ" fighter["熊谷"] = "黒色メガね" fighter["公昭"] = "グレーのメガネ" fighter["山田"] = "新しいメガネ" fighter["ひでぷー"] = "年季入ったメガネ" p fighter # Hash の中身を確認する c.もとのプログラムの変更点 授業時に作ったプログラム shop.rb を参考にして作りました。 d.実行した結果画面 irsv{c106026}% ./fighter.rb [~/Ruby] {"山田"=>"新しいメガネ", "公昭"=>"グレーのメガネ", "小林"=>"青色メガネ", "熊谷"=>"黒色メガね", "ひでぷー"=>"年季入ったメガネ", "志賀"=>"紺色メガネ"} e.結果の考察 最初にプログラムを実行した際に、プログラムが起動しなかった。これは対にな る人物の特徴を " (ダブルコーテーション) でくくっていなかったためである。 数字の場合くくる必要はないのだが、文字になると " (ダブルコーテーション) でくくらないとプログラムが起動しないことがわかった。 f.参考文献 西村先生のホームページのこれはいくらを参照した。 URL:http://roy/~madoka/2007/r2/02/02-02-hash.html (お詫び) 本来なら、あらかじめプログラムに登録してある対を表示するものを hash-for.rb で作成しなければならないのですが、初めにユーザが知りたい 情報だけを表示するプログラムを hash-for.rb で作成してしまいました。その ため、あらかじめプログラムに登録してある対を表示するプログラムを fighter.rbで作成したことをここにお伝えします。 a.考えた設定 その人がどんなメガネをかけているのかが、わかってしまうプログラム。 hash-for.rb ユーザーが知りたい情報を表示させるプログラムを作りました。 b.作成したプログラム #!/usr/koeki/bin/ruby $KCODE = 'e' # 日本語コード EUC で出力する fighter = Hash.new # Hash 配列を fighter と定義する fighter["志賀"] = "紺色メガネ" fighter["小林"] = "青色メガネ" fighter["熊谷"] = "黒色メガネ" fighter["公昭"] = "グレーのメガネ" fighter["山田"] = "新しいメガネ" fighter["ひでぷー"] = "年季入ったメガネ" #p fighter print("今度メガネ買うなら、メガネ市場がいいですよ!\n")# print("") # print 文という実行文。 sleep 2 # 2 秒間間があく print("誰のメガネが気になりますか?\n") sleep 2 print("次の中から名前を入力して下さい\n") sleep 2 print("志賀、小林、熊谷、公昭、山田、ひでぷー\n") STDERR.print("名前:\n") name = gets.chomp # 入力されたデータをとりこむ method #p fighter.key?(name) if fighter.key?(name) == false # if - end の条件文 printf("%sは存在しませんので、打ち直してねー。\n",name) sleep 1 print("うえぇぇぇぇぇぇー\n") sleep 2 print("載ってない名前を打つんじゃねー\n") sleep 2 print("でもそんなの関係ねぇぇぇぇぇぇー\n") sleep 2 print("でもそんなの関係ねぇぇぇぇぇー\n") sleep 2 print("でもそんなの関係ねぇぇぇぇー\n") sleep 3 print("はい、オッパっピー\n") sleep 2 print("チントンシャンテントン\n") sleep 2 print("チントンシャンテントン\n") sleep 2 print("終りかたがわからない\n") sleep 2 print("でもそんなの関係ねぇぇぇぇぇー\n") sleep 2 print("でもそんなの関係ねぇぇぇぇー\n") sleep 3 print("はい、オッパっピー\n") else printf("%sは%sだよー\n",name,fighter[name]) end # if に対応する end c.もとにしたプログラムからの変更点 授業時に作成した shop.rb をもとに作成した。shop.rb に gets.chomp で入力 したデータを取り出せるようにした。 d.実行した結果画面 <選択肢にある名前を入力した場合> irsv{c106026}% ./hash-for.rb [~/Ruby] 今度メガネ買うなら、メガネ市場がいいですよ! 誰のメガネが気になりますか? 次の中から名前を入力して下さい 志賀、小林、熊谷、公昭、山田、ひでぷー 名前: 志賀 志賀は紺色メガネだよー <選択肢にない名前を入力した場合> irsv{c106026}% ./hash-for.rb [~/Ruby] 今度メガネ買うなら、メガネ市場がいいですよ! 誰のメガネが気になりますか? 次の中から名前を入力して下さい 志賀、小林、熊谷、公昭、山田、ひでぷー 名前: 志田 志田は存在しませんので、打ち直してねー。 うえぇぇぇぇぇぇー 載ってない名前を打つんじゃねー でもそんなの関係ねぇぇぇぇぇぇー でもそんなの関係ねぇぇぇぇぇー でもそんなの関係ねぇぇぇぇー はい、オッパっピー チントンシャンテントン チントンシャンテントン 終りかたがわからない でもそんなの関係ねぇぇぇぇぇー でもそんなの関係ねぇぇぇぇー はい、オッパっピー e.結果の考察 始めに作ったプログラムをもとにして、ユーザーが知りたい情報を表示するプロ グラムにうまく組み込むことができた。 また、sleep を入れて文字が一気に表示されないようにして、見やすさと読みや すさを気をつけた。 f.参考文献 西村先生のホームページを参照し、プログラムを作成した。第二回なになにといえ ばこれこれ-Hash(連想配列) URL:http://roy/~madoka/2007/r2/02/index.html データから読み込むようにしたプログラム hash-hash.rb a.考えた設定 hash.dat を作成して、その入力したデータを読み込み表示させる プログラムを作りました。 b.作成したプログラム hash-hash.rb #!/usr/koeki/bin/ruby STDERR.print "fighter の名前を入力して下さい" # STDERR.print # 標準エラー出力で printf を実行する pattern = STDIN.gets.chomp request = Regexp.new(pattern, true, "e") open("hash.dat","r") do |candidate| #読み込むのでモードは r(Read)。 while hash = candidate.gets if request =~ hash # print hash if /(\S+)\s+(\S+)\s/ =~ hash # \S #1 文字 # \s # 1 空白文字 printf("%s\n", $1) #取り出したい名前の列 printf("%s\n", $2) #取り出したいメガネの列 end end end end 作成したデータ hash.dat 志賀 紺色メガネ 小林 青色メガネ 熊谷 黒色メガネ 公昭 グレーのメガネ 山田 新しいメガネ ひでぷー 年季入ったメガネ c.もとのプログラムからの変更点 一つのデータだけではなく、その人の全てのデータを表示させるようにした。 d.実行した結果 irsv{c106026}% ./hash-hash.rb [~/Ruby] : 公昭 公昭 グレーのメガネ e.結果の考察 データから読み込むようにしたプログラムへ変更するということで、データ である hash.dat を作成して、そこから入力されたデータを読み込むようにした。 これで合っているのでしょうか…不安です。 hash.dat を作らずに、プログラムか らデータを読み込めるようなプログラムを将来完成させたいです。 f.参考文献 西村まどか先生のホームページを参照して作成しました。基礎プログラミング I の「データを読み込むようにするには」 URL:http://roy/~madoka/2007/r1/07/07-10-readdata.html プログラムで対を登録し、表示させるプログラム hash-register.rb a.考えた設定 名前、どんなメガネかを入力すると、最後に入力した文字一覧が出るプログラム。 b.作成したプログラム #!/usr/koeki/bin/ruby fighter = Hash.new("") print("名前を入力して下さい \v 終了は Ctrl D\n") while true STDERR.print("名前: \n") name = gets #名前を name で表した。 if name == nil break else name = name.chomp end STDERR.print("どんなメガネ:\n") status = gets.chomp #どんなメガネかを status で表した。 fighter[name] = status end $KCODE = 'e' #日本語コード EUC で出力する #p fighter for name,status in fighter printf("%s\t%s\n",name,status) end c.もとにしたプログラムの変更点 授業時に作成した、pair.rb をもとにしてプログラムを作成した。 d.実行した結果画面 irsv{c106026}% ./hash-register.rb [~/Ruby] 名前を入力して下さい 終了は Ctrl D 名前: ひでぷー メガネの状態: 年季が入ったメガネ 名前: 山田 メガネの状態: 新しいメガネ 名前: 山田 新しいメガネ ひでぷー 年季入ったメガネ e.結果の考察 1.の始めに対にした 6 人の他に、違う名前を入力しても表示されてしまう。 下記を参照していただきたい。 irsv{c106026}% ./hash-register.rb [~/Ruby] 名前を入力して下さい 終了は Ctrl D 名前: 加藤 どんなメガネ: だてメガネ 名前: 井上 どんなメガネ: 裸眼 名前: 井上 裸眼 加藤 だてメガネ f.参考文献 西村先生のホームページを参照した。第二回「Hash の対を入力するには」 URJ:http://roy/~madoka/2007/r2/02/02-06-input-hash.html 4. <考察> データファイル words.dat を作成したものの、単語帳 wordbook.rb をどう作 成したらよいかわからなかった。おそらく open -- end と他のプログラムを 組み合わせて作るのではないかと予想した。 途中ではありますが、作成したプログラムを載せておきます。自分は、前に作 成した hash-register.rb と open -- end を組み合わせればできるのではな いかと考え wordbook.rb を作成しました。 作成したプログラム #!/usr/koeki/bin/ruby fighter = Hash.new("") print("名前を入力して下さい \v 終了は Ctrl D\n") while true STDERR.print("名前: \n") name = gets #名前を name で表した。 if name == nil break else name = name.chomp end STDERR.print("どんなメガネ:\n") status = gets.chomp #どんなメガネかを status で表した。 fighter[name] = status end $KCODE = 'e' #p fighter for name,status in fighter printf("%s\t%s\n",name,status) end open("words.dat","r") do |candidate| while words = candidate.gets if request =~ words # print words if /(\S+)\s+(\S+)\s/ =~ words printf("%s\n", $1) printf("%s\n", $2) end end end end 実行結果 irsv{c106026}% ./wordbook.rb words.dat [~/Ruby] 名前を入力して下さい 終了は Ctrl D 名前: どんなメガネ: 名前: どんなメガネ: 名前: どんなメガネ: ./wordbook.rb:19: private method `chomp' called for nil (NameError) 5.感想 進数計算をすっかり忘れていたため、最初何が何だかわからなかった。そこで、 前期のレポートを振り返ってある法則があることを思い出した。 10 進数から 2 進数にするとき → 2 で割っていく 2 進数から 16 進数にするとき → 4 桁ずつ区切って、当てはめる 2 進数から 10 進数にするとき → 2 乗をかけていく プログラムは授業中作成したプログラムを参考に作成まで辿り着いた。作成を通 してHash 配列や open -- end を復習できた。今回何度もお世話になったのは、 「 Hash の対を新しく入力するには」と基礎プログラミング I の「データを読み 込むようにするには」である。その他過去の自分のプログラムを参考にして作 りました。 次回からは、法則を頭に置いて臨むとともに、open -- end 等の前期で学んだ事 を復習して徐々に思い出していきたい。 てんぷできましたー。