• ベストアンサー

Rubyの初心者ですが壁にぶちあたっております

『初めてのプログラミング』を読んでRubyを勉強しています。その中にある問題でp.127の『ローマ数字をアラビア数字に変換するプログラム』を書け、というのがありまして、最初に入力したローマ数字を弾く部分を書いているのですが…(以下コード) puts 'Enter roman numeral.' roman = gets.chomp.upcase roman_array = roman.to_a def char_checker(char) parts = ['I', 'V', 'X', 'L', 'C', 'D', 'M'] parts.each do |part| if part != char char = false elsif part == char char = true return char end end puts char_checker('X') (以上コード) このchar_checker, なぜかpartsを返してきます。返してほしいのはcharのtrueかfalseなのに泣 書いたコードに間違いがあるのはわかっているのですが、どこで間違っているのかがどうしてもわかりません。わかる方回答よろしくお願いします。ちなみに環境はMac OS X 10.5.4でrubyのバージョンはバンドルされている1.8.6です。

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

>変数の使い回しとは配列のpartsと|part|のことでしょうか。 いえ、ちがいます。 def char_checker(char) ← のchar と char = false char = true で使っている char のことです。 > イテレータ部分の最初でcharがfalseに変えられてしまうの で、elsif part == charに引っかからなくなってました。 はい。そういうことです。 > 最後に評価された文だから'M'だけ出力されるはずなのに… いいところをついていますが、ちょっと違います。 確かにメソッドに return がない場合には最後に実行された文(式)の値が メソッドの返す値になるというのはそのとおりなんですが、 「最後に実行されたものは何か」ということです。 実はrubyでは、if 文なども値を返します。そして今回のように [配列].each do ... end も同じなんです。 irb というコマンドを使うと対話的にRubyが実行できるので試してみてもらいたいのですが、 irb(main):009:0> ['h', 'e', 'l', 'l', 'o'].each {|e| e[0]} => ["h", "e", "l", "l", "o"] irb(main):010:0> ['h', 'e', 'l', 'l', 'o'].each {|e| puts e[0]} 104 101 108 108 111 => ["h", "e", "l", "l", "o"] irb(main):011:0> この、=> の後に書かれているのがこの each を含んだ文の「値」です。 ということは、 def char_checker(char) このメソッドの「最後の文」は each do end の中にある文ではなくて、each している文そのものなんです。 ということで配列の中身であるI V X L C D M が全部出てきているというわけです。 そしてもうひとつ irb(main):001:0> def hoge irb(main):002:1> puts "hoge が呼ばれました" irb(main):003:1> "hello!" irb(main):004:1> end => nil irb(main):005:0> hoge hoge が呼ばれました ← メソッドの中の puts で出力されたもの => "hello!" irb(main):006:0> puts hoge hoge が呼ばれました ← メソッドの中の putsで出力されたもの hello! ← メソッド hogeの戻り値を puts した結果 => nil ← puts hoge の「値」 puts という「文の値」が nil なので > def文の最後にputs 'Lucky Stirike'と入れるとpartsの中身は出力されなくなりLucky Strikeと出力されました。 となるわけです。 こんなんで納得できますか?

sa1986
質問者

お礼

すっきりしました。irbすごい便利ですね!ありがとうございます。これからirbを駆使してこのプログラムを完成させたいと思います。またお世話になるかもしれませんが、その時はよろしくお願いします(^_^;)

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

> どこで間違っているのかがどうしてもわかりません。 実行時のエラーメッセージの全文を正確に提示してください。 ところで、 > roman = gets.chomp.upcase > roman_array = roman.to_a この部分の意図は、どういったものでしょうか。 > puts char_checker('X') ここで'X'固定にしている訳も教えてほしいです。

sa1986
質問者

お礼

>実行時のエラーメッセージの全文を正確に提示してください。 えーと、エラーではなくてちゃんと実行されるのですが思った通りに動いてくれなかったんです。 >この部分の意図は、どういったものでしょうか。 これは実験で、Xだとどう動いてくれるかな~と思ってしました。 他の方の回答で解決しましたが、丁寧に回答していただきありがとうございます!!

全文を見る
すると、全ての回答が全文表示されます。
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

変数の使い回しは止めましょう。 メモリを節約しているつもりかもしれませんが、意味ありません。 で、char_checker に一行書き加えて、何がどうなっているのかよく考えてみてください。 def char_checker(char) parts = ['I', 'V', 'X', 'L', 'C', 'D', 'M'] parts.each do |part| puts "char=#{char}, part=#{part}" #追加 if part != char char = false elsif part == char char = true return char end end end

sa1986
質問者

補足

アドバイスありがとうございます!!変数の使い回しとは配列のpartsと|part|のことでしょうか。メモリの節約とかそんな高度なことは考えてなかったんですが… 追加部分を加えて再度実行してみたところ、 bash-3.2$ ruby roman_arabian_again.rb char=X, part=I char=false, part=V char=false, part=X char=false, part=L char=false, part=C char=false, part=D char=false, part=M I V X L C D M と出ました。イテレータ部分の最初でcharがfalseに変えられてしまうので、elsif part == charに引っかからなくなってました。 puts "char=#{char}, part=#{part}"←こんなチェックの仕方があるとは知りませんでした。勉強になります! それで、配列"parts"の中身が出力されている件なんですが、試しにdef文の最後にputs 'Lucky Stirike'と入れるとpartsの中身は出力されなくなりLucky Strikeと出力されました。おそらくputs char_checker('X')で、char_checkerが"最後に"評価した文(この場合はif part != char)をputsに渡してるんだろうと思います。しかしそうだとすると最後に評価された文だから'M'だけ出力されるはずなのに… おこがましいですが何かお答えいただけたらと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • siffon9
  • ベストアンサー率64% (136/211)
回答No.1

このプログラムだとifに対応するendが無くてエラーになりますけど。

sa1986
質問者

お礼

ご指摘ありがとうございます。プログラム自身はちゃんと書いてあるんですが手打ちで書いたんでendが一つ抜けてしまいました。これからはコピペするようにします。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • rubyの構文(&&を用いた条件分岐について)

    ruby初心者です。 最近、ruby on railsで書かれたソースを引き継ぎ解析を行っています。 その中で、以下のような構文が出てきました。 ========================================= num = 0 bool = false vals = '' puts 'start' num == 0 && bool && if vals  puts 'true' else  puts 'false' end puts 'end' ========================================= 上記プログラムを実行すると、if ~ end までが実行されませんでした。 そこで、変数boolをtrueに変更して再実行したところ、if文が実行されました。 そこで私は、上記プログラムは以下と同値であると解釈しました。 ====================================== (省略) if num == 0 && bool  if vals   puts 'true'  else   puts 'false'  end end ======================================= 以上を踏まえて・・・ 1.私の解釈は正しいでしょうか? 2.間違っている場合、正しい処理の解釈を教えていただけますでしょうか?または参考URLを教えていただけますと助かります。 文の最後に"&&"がついている文を見たことがなく、ネットで調べても 正解らしいものが掲載されていなかったので質問させていただきました。 拙い説明で申し訳ありませんが、よろしくお願いいたします。

    • ベストアンサー
    • Ruby
  • Ruby初心者です。

    以下の練習問題をやっているのですが、どうもうまくいきません。 (1)担当名が"end"になる迄、担当名と売上を入力する。 (2)売上合計を求める。 (3)各担当の売上が売上合計の何%になるかの比率の計算を行う。 (4)担当名、売上、比率を表示する。 どこがいけないのがご教授頂けますでしょうか。 よろしくお願い致します。 *********************************** #! ruby -E Windows-31J:utf-8 # coding: utf-8 kensu = 0 uriage = 0 goukei = 0 uriage_t = [20] tanto = [10] tanto = [20][10] puts("担当名がendで終了") print(kensu = kensu + 1, "人目の担当名は") tanto = $stdin.gets.chomp! tanto.gsub!("\n", "") print("売上") uriage = $stdin.gets.chomp!.to_i while tanto != "end" kensu = kensu goukei = goukei + uriage uriage_t = uriage tanto_t = tanto print(kensu = kensu + 1, "人目の担当名は") tanto = $stdin.gets.chomp! tanto.gsub!("\n", "") if tanto != "end" print("売上") uriage = $stdin.gets.chomp!.to_i end end kensu = kensu + 1 goukei = goukei + uriage uriage_t = uriage tanto_t = tanto, "合計" puts "________________________________________" puts "  担当      売上  比率  " puts "________________________________________" for i in kensu kensu += i ritu = uriage * 100 / goukei puts "担当名は#{tanto} 売上は#{uriage_t}円 比率は#{ritu}%" end

  • Rubyの引数が理解できません。(初心者です)

    プログラミング言語を覚えたいと考え、諸々の事情からRubyを独学したいとおもっております。 先日、「14歳からはじめるRuby…」という本を購入し、早速勉強を始めたのですが、引数でいきなり躓いてしまいました。 以下のような例文がありましたが、原理(理屈?)が理解できません。ご教唆お願いします。 001 def syomei s 002  puts "" 003  puts "============" 004  puts "" + s 005  puts "============" 006 end 007 puts "What's your name?" 008 name = gets.chomp 009 puts "Hello," + name + "!" 010 syomei name なぜ、これでメソッドの中へ変数が引き渡されるのかが理解できません。 「008 name」で初めて出てくるnameと引数"s"が何故イコールになるのでしょうか? 例えば(全くのデタラメですが)、「010 syomei name.s」であったり「010 syomei name = s」などのように定義付けされているのであれば、納得できるのですが…。 初歩中の初歩なのはわかっているのですが、理屈を理解したいと思ってます。よろしくお願いします。

  • rubyのプログラム

    プログラミング初心者です。参考書のソースコードをそのままコピペして実行したのですが、エラーが出てしまいます。どこが間違っているのかご指摘いただけると助かります。 ソースコード #encoding: cp932 # うるう年かどうかによって時間数は変わります puts 24*365 puts " (#{24*366}になる場合もある) " 実行結果 >ruby calc.rb calc.rb:4: invalid multibyte char (Windows-31J) calc.rb:4: syntax error, unexpected tIDENTIFIER, expecting $end puts "(#{24*366}になる場合もある)" ^ >Exit code: 1 パソコンOS Windows7 rubyのバージョン 1.92

    • ベストアンサー
    • Ruby
  • 【ruby】【文法?】ブロックをbreakした時。。

    質問を見ていただいて有難うございます。 質問を一言で言うと、 「メソッドの中で呼び出し元がbreakを使った事を検知できるか?」 となるのでしょうか。。。以下に詳しく質問を記述いたします。 引数に配列を渡すと、その配列をブロックに一つずつ返してくれる メソッドhoge()があるとします。 以下の様に使います。 ------------------------------------- hoge([0,1,2]) do |x|  puts x end 実行結果 0 1 2 ------------------------------------- このhoge()は、実行中にエラーが発生した場合、トラップして falseを返す事とします。(何事もなければtrueを返します。) このhoge()を以下の様に書きました。 def hoge(arg)  begin   arg.each do |x|    yield x   end  rescue   false  else   true  end end 以下の様に使います。 ------------------------------------- ret=hoge([0,1,2]) do |x|  puts x end puts ret ? 'success' : 'fail' 実行結果 0 1 2 success ------------------------------------- ------------------------------------- ret=hoge(nil) do |x|  puts x end puts ret ? 'success' : 'fail' 実行結果 fail ------------------------------------- ここまでは、よかったのですが、hoge()のブロックの中で、breakを使うと hoge()の戻り値はnilになってしまいます。 ------------------------------------- ret=hoge([0,1,2]) do |x|  break if x==1  puts x end puts ret puts ret ? 'success' : 'fail' 実行結果 0 nil fail ------------------------------------- ここで質問です。 最後の例は、hoge()として異常系ではないので、retにtrueを与えたいのですが、どうしたらよいでしょうか? ご指導のほど、宜しくお願いいたします。

    • ベストアンサー
    • Ruby
  • 【Ruby初心者】簡単なプログラムが実行しない

    教材でRubyを勉強中なのですが、以下のプログラムが実行されず爆死しています。 --- puts("整数を入力してね") number = gets.to_i if number > 0 then puts("正の数です!”) end --- 文字コードは、UTF-8で指定、OSはMacです。CotEditorを使用しています。 数字/アルファベットだけのプログラムは正常に実行されるのですが、 文字入りのプログラムがうまく実行されません。 プレビュー見ると文字化けしているので(添付画像参照)、 文字入力にバグが起因していると思われますがお手上げ状態です。

    • ベストアンサー
    • Ruby
  • Ruby バブルソート

    バブルソートのプログラムでわからないところがあるため、 質問させていただきます。 Rubyは1.9.3を使用しています。 <プログラム> --------------------------------------------------- def bsort(data)   while true     # swapped変数は数値の入れ替えを記憶     swapped = false     for i in 0..data.size-2       if data[i] > data[i+1]         temp = data[i]         data[i] = data[i+1]         data[i+1] = temp         swapped = true       end     end     return if !swapped   end end data = [10, 9, 8, 7, 6] bsort(data) puts "ソート結果#{data}" --------------------------------------------------- return if !swapped のところで、 なぜwhileのループから抜けられるのかがよくわかりません。 return if swapped == false と書き換えて実行しても同じ結果が得られたのですが、 数値の入れ替えがなければ swapped = false であるため、 !swappedはtrueとはならないのでしょうか。

  • Rubyのirbで計算を途中でやめることは可能?

    (OS: Mac OS X 10.9.1, Rubyのバージョン: 2.0.0 です) Ruby の irb を使用していて, 例えば >> while true >> puts "infinite loop" >> end などと打ち込んでしまって無限ループが起きたときや, その他非常に時間がかかりそうな計算を行っているときに, これを中断する手段というのはあるのでしょうか? (control + Z をすれば irb 自体を中断することはできるようですが, irb自体は中断せずに, 現在行っている処理のみを停止したいということです.)

    • ベストアンサー
    • Ruby
  • Ruby1.9.2でマジックコメントが反映されない

    基本的な質問になるのですが、 CentOS5.5でRuby1.9.2を利用しているのですが、スクリプト中に、マジックコメントを 入れているにも関わらず、「invalid multibyte char」エラーが返ってきます。 追加で設定する情報があるのでしょうか。 お手数お掛けしますが、ご存知の方がいらっしゃれば、ご教示ください。 # ruby -v ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux] # cat hello.rb # -*- encoding: utf-8 -*- puts 'こんにちは' # ruby -v hello.rb ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux] hello.rb:2: invalid multibyte char (UTF-8) hello.rb:2: invalid multibyte char (UTF-8) # ruby -Ks hello.rb hello.rb:2: invalid multibyte char (UTF-8) hello.rb:2: invalid multibyte char (UTF-8)

    • ベストアンサー
    • Ruby
  • 検索対象を変数に与えてマッチング

    Rubyの初心者です。次のサンプルがマッチングできない、 書き方を教えてくださいませんか。 #!/usr/bin/env ruby key = "キーワード" while gets $_.chomp! puts $_ if $_ =~ /"#{key}"/ end puts 文を puts $_ if $_ =~ /キーワード/ に書き買えば、検索はできますが、変数に与えてマッチング することはできないでしょうか。 ご教示を宜しくお願いします。

    • ベストアンサー
    • Ruby
このQ&Aのポイント
  • 前月や前週のデータを仕訳データ入力できない状況に悩んでいますか?解決方法をご紹介します。
  • 仕訳データ入力時に「書き込みできません」と表示される場合、前月や前週のデータの入力方法に注意が必要です。
  • 前月や前週のデータの入力時にエラーが発生してしまう場合、日付や月の指定が間違っている可能性があります。
回答を見る