質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

4回答

976閲覧

rubyでの2つの整数を比較の仕方について

mifne

総合スコア20

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2019/02/09 23:03

開発環境 

ruby version 2.3.3p222

ご用件

######rubyで2つの整数を比較して大きい方を表示するプログラムをつくっています。
####エラーのNilClassがなぜ出るのか、どうすれば改善するかわかりません。
どうかご教授ください。

発生している問題・エラーメッセージ

Main.rb:5:in `<main>': undefined method `chomp' for nil:NilClass (NoMethodError)と返ってきました。

該当のソースコード

ruby

1i = 0 2while i < 10 do 3s = gets.chomp.split(" ") 4 if s[0] > s[1] 5 puts "#{s[0]}" 6 7 elsif s[1] > s[0] 8 puts "#{s[1]}" 9 10 elsif s[1] == s[0] 11 puts "eq" 12 end 13 i += 1 14end

試したこと

googleで検索してみたけれども、ぜんぜんりかいすることができませんでした。すいません。
0.
会社を辞めて在宅ワーカーになったパパの記録]
0. リンク内容

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

undefined method `chomp'

とのことなので

問題はgetsがnilを返していることです。

Kernel.#getsを見ると

ファイルの終り(EOF)に到達した時、 nil を返します。

と書いてあります。

なので対策としては、

  • getsをしたあとにnilチェックをしてからchomp.split(" ")をする
  • 入力データの仕様を見直す

コード上では10件分のデータが書いてあるのを想定しているが、データが足りていない


puts "#{s[0]}"

単にputs s[0]でいいです。

if s[0] > s[1]

これが整数比較になるかは微妙です
文字列をsplitしただけなのでs[0] s[1]ともに文字列のままです。
あくまでs[0] s[1]が数値文字列であった場合
長さ順・辞書順による比較が行われ似たような結果が返りますが
先頭に0を入れた場合などに誤った結果となるでしょう

投稿2019/02/09 23:37

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mifne

2019/02/09 23:51

ご回答いただきありがとうございます。
guest

0

UFOではどうでしょう?

puts "2つの数字を空白で区切って入力してください" 10.times { s0,s1=gets.split.map(&:to_i) case (s0 <=> s1) <=> 0 when 0 puts :eq when 1 puts s0 else puts s1 end }

イメージ説明
参考
https://qiita.com/jkr_2255/items/51ecffeaf62e15d9a782

投稿2019/02/11 10:39

DrqYuto

総合スコア432

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mifne

2019/02/13 06:25

わざわざご回答いただきありがとうございます。 このような書き方、短くて便利です。 わかりやすく書く方法が分かって良かったです。 ありがとうございます。
DrqYuto

2019/02/13 09:39

競プロでよく使ってたので使えますよ
guest

0

繰り返しの回数が10回と決まっているのなら、iを使わず10.times do 〜 endの方が簡潔です。

ただし、10回と決めうちするのが原因でgetsnilを返す可能性があるのだとすると、

ruby

1while line = gets 2 s0, s1 = line.split.map.(&:to_i) 3 if s0 > s1 4 puts s0 5 elsif s1 > s0 6 puts s1 7 elsif s1 == s0 8 puts "eq" 9 end 10end

というように、getsにちゃんと入力がある間だけ、whileのボディを実行するように書き換えて見るのもいいかもしれません。

なお、line.splitすると、末尾の改行が取れるので(改行もwhitespaceの一種です)、chompする必要はありません。

また、配列内の文字列を一気に整数に変換するのなら、map(&:to_i)が便利です。

そして、その返り値である配列を変数sに代入して使うより、s0, s1 = 〜というように、多重代入して整数ごとに変数に代入した方が分かりやすいように思いました。


【追記】
超トリッキー版です。

ruby

1while line = gets 2 s0, s1 = line.split.map.(&:to_i) 3 puts ["eq", s0, s1][s0<=>s1] 4end

投稿2019/02/10 01:00

編集2019/02/10 02:46
kts_h

総合スコア207

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mifne

2019/02/10 01:50

こんなにも丁寧にご回答頂きありがとうございます。 とてもあったかい気持ちになります。 知らないことが多いため、回答を参考にして作り直したいと思います。 どうもありがとうございます。
kts_h

2019/02/10 02:14

どういたしまして。 ついでに、比較して表示する部分ですが、トリッキーな方法を思いついてしまいました。演算子「<=>」は、左が大きいと1、等しいと0、右が大きいと-1を返すので、「puts ["eq", s0, s1][s0<=>s1]」で表現できます。
mifne

2019/02/10 02:51

面白い発想ですね。こんな記述法があるとは思いませんでした。 puts ["eq", s0, s1][s0<=>s1] 自分のコードにも実装させていただきます。 アドバイスありがとうございます。
guest

0

2つの数字をいれていないときのチェックをしていないことが原因です。
つぎのようにチェック処理を追加してみてください。

ruby

1i = 0 2while i < 10 do 3 s = gets.chomp.split(" ") 4 if s.size < 2 5 puts "2つの数字を空白で区切って入力してください" 6 next 7 end 8 9 if s[0] > s[1] 10 puts "#{s[0]}" 11 elsif s[1] > s[0] 12 puts "#{s[1]}" 13 elsif s[1] == s[0] 14 puts "eq" 15 end 16 i += 1 17end

実行例
イメージ説明

イメージ説明

追記
コメントでのやりとりのことやエラーチェックを強化したコードを示します。
(数値であることのチェックの追加、数字として大小比較をする)

ruby

1i = 0 2while i < 10 do 3 s = gets.chomp.split(" ") 4 5 if s.size != 2 6 puts '2つの数字を空白で区切って入力してください' 7 next 8 end 9 unless s[0] =~ /^[0-9]+$/ && s[1] =~ /^[0-9]+$/ 10 puts '整数を入力してください' 11 next 12 end 13 14 s[0] = s[0].to_i 15 s[1] = s[1].to_i 16 if s[1] == s[0] 17 puts 'eq' 18 else 19 puts s.max 20 end 21 i += 1 22end

s[0], s[1] のチェック、整数への変換はコードが重複しています。
map メソッドをつかうと短く書くことが可能です。興味があれば map メソッドをつかって書き直してみてください。

投稿2019/02/09 23:16

編集2019/03/05 13:34
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mifne

2019/02/09 23:25

ご丁寧に回答いただきありがとうございます。 ですが実行してみても、改善されませんでした。 Main.rb:3:in `<main>': undefined method `chomp' for nil:NilClass (NoMethodError) 申し訳ないのですが、もう一度ご回答いただけませんか。
katoy

2019/02/10 00:01

なにを入力したらエラーになったかを教えてください。
mifne

2019/02/10 01:59 編集

すいません。上のエラーは直りました。お騒がせしてすいません。 ですが、 90 100 と入力すると90 90と返ってきました。100とは返ってきません。 なぜだか教えてください。
katoy

2019/02/10 02:03

別回答にあるように 文字列として比較をしているからです。 s0 = s[0].to_i と s1 = s[1].to_i と整数に変換してから s0, s1 を比較するようにしてみてください。
mifne

2019/02/10 02:22

例を示して、教えてくれてありがとうございます。 すぐに、質問にもお答えいただいて、感無量です。 とてもわかり易かったです。
katoy

2019/02/10 02:34

整数に変換する処理を追加したコードを回答に追記しました。
mifne

2019/02/10 02:37

コードの改定ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問