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

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

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

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

Q&A

解決済

5回答

1588閲覧

条件の処理がうまくいかない

KentaTsujino

総合スコア13

Ruby

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

1グッド

1クリップ

投稿2019/02/01 03:55

前提・実現したいこと

はじめまして、Kentaと申します。
case,when のコマンドを練習するためにプログラムを組んでみたのですが、うまく処理されずに困っています。

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

カウンターのようなものを作ってみました
プログラム自体は動作していて、エラーメッセージは出ていません。
条件文で、変数が他方の変数より小さいときの処理をつくっているのですが、この部分が処理されません。

該当のソースコード

Ruby

puts 'カウンター'
puts '何度数えますか?'
n = gets.to_i
a = 0
while true
case a
when a<n ###この部分がスキップされてしまいます
puts'数える?(1)数えない?(0)'
input = gets.to_i
case input
when 0
puts '初めに戻ります'
when 1
puts '数えます'
sleep 1
a += 1
puts '現在'
print a
print '/'
puts n
end
when a=n ###ここが常に出てきます。
sleep 1
puts '完了!'
exit
end
end

試したこと

いくつかの数字を代入してみましたが、どの場合も when a=n の処理だけ行われました。
初学者なりにコードを見直してみましたが、いまいちどこが悪かったのかわかりません。
お力をお貸ししていただけますと幸いです。

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

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

DrqYuto👍を押しています

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

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

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

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

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

guest

回答5

0

挙動は知りませんが、
case whenって比較演算子(<とか=とか)使えましたっけ?
case whenの仕様を見直してみましょう。

-追記------------------------------------------------------

a=5 case when a < 4 p "4" when a < 7 p "7" #=>7が表示される when a < 10 p "10" end

出来るんですね、勉強になりました。

投稿2019/02/01 04:24

編集2019/02/01 06:04
torisan

総合スコア678

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

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

KentaTsujino

2019/02/01 04:53

簡潔な回答ありがとうございました、無事解決できそうです!
guest

0

case a で頑張りたいのなら、when a < nwhen ->(x) { x < n } に書き換える方法も考えられます。まあ、今回の場合、お勧めではありませんが。

when 節に Proc オブジェクトを持ってくると、case 節にある a を引数にして Proc オブジェクトが実行されます。

上記のように書き換えた場合、実行されるのは ->(x) { x < n }.call(a) で、実質的には、a < n と同じです。

そして、true が返ると、お目当ての puts'数える?(1)数えない?(0)' が実行されて、目的達成となります。

投稿2019/02/01 14:34

編集2019/02/01 14:41
kts_h

総合スコア207

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

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

0

case a <=> n

とすると、 when 1, when 0, when -1 で処理分岐ができます。

それをつかって書いてみました。
想定外の入力があった場合 (a に負値や数字以外を指定するなど) にもある程度対応してみています。

ruby

1puts 'カウンター' 2puts '何度数えますか?' 3n = gets.to_i 4 5a = 0 6while true 7 case a <=> n 8 when -1 9 puts '数える?(1), 数えない?(0)' 10 input = gets.to_i 11 case input 12 when 0 13 puts '初めに戻ります' 14 else 15 puts '数えます' 16 a += 1 17 end 18 when 0, 1 19 puts '完了!' 20 break 21 end 22 puts "現在 #{a}/#{n}" 23end

投稿2019/02/01 12:49

katoy

総合スコア22324

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

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

0

ruby

case a
when a<n ###この部分がスキップされてしまいます
...
end

ここはaa<nと同じであれば処理されます。((a < n) === a #=> false)
常にfalseが返ってくるので絶対に実行されません。
ちょっと言語化が難しいですが「aa < nである時」とは異なります。(a=0 < n=1 #=> true)

ruby

when a=n ###ここが常に出てきます。

また(a = n) === aは2回目以降は常にtrueです。

case文をあまり理解できていないように見受けられます。
今回の場合はcase文ではなくif文を使ったほうがいいでしょう。

ruby

1puts 'カウンター' 2puts '何度数えますか?' 3n = gets.to_i 4a = 0 5while true 6 if a < n 7 puts'数える?(1)数えない?(0)' 8 input = gets.to_i 9 10 case input 11 when 0 12 puts '初めに戻ります' 13 when 1 14 puts '数えます' 15 sleep 1 16 a += 1 17 puts "現在 #{a}/#{n}" 18 end 19 20 elsif a == n 21 sleep 1 22 puts '完了!' 23 exit 24 end 25end

他にも 何度数えますか? でマイナスの値を入力すると無限ループしますし
数えるか数えないかの入力値が 0か1 以外だった場合の処理もないので
今後その辺りの処理も考えてみると良さそうです。

投稿2019/02/01 05:04

編集2019/02/01 06:21
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

otn

2019/02/01 05:21

細かいですが、=== の左右が逆です。
退会済みユーザー

退会済みユーザー

2019/02/01 05:38 編集

case obj when mod end の時 mod === obj でした、逆に覚えてました...。 指摘ありがとうございます。修正しておきます。
KentaTsujino

2019/02/01 05:43

なるほど、Case a When a<n は決して成り立たないためにスキップされていたんですね! 重ねての質問ですみませんが、a === a=n が2回目以降必ず True となるのはどうしてなのですか? 具体的にn=2 の場合で考えてみたのですが、aに数字を加える処理が行われていないためa=0で、a = n は成り立たないのではないでしょうか? それともa=nの真偽に関わらず、a === a が成り立っているのでこちらの処理が行われているということなのでしょうか? その場合、どうして1度目で処理されないのでしょうか? 的外れな質問でしたらすみません。 とても丁寧な回答ありがとうございました。手直しまでしていただいてたいへん勉強になります。
退会済みユーザー

退会済みユーザー

2019/02/01 05:52 編集

a === a=n に関してですが1度目の比較でaにnが代入されるので 2回目以降は実質 a=n === a=n の評価になるためです。 加えてaに値が加算される処理が必ず実行されないのも相まって常にtrueが返る結果になっています
退会済みユーザー

退会済みユーザー

2019/02/01 05:55

すみません違いました。 先ほどの === が逆だったのでここの部分も間違えていました。
退会済みユーザー

退会済みユーザー

2019/02/01 05:58 編集

正しくは a = n === a になるので a には n === a の結果が代入されます。 なので最初の n === a の結果がtrueであれば以後常に true false であれば以後常に false といった具合になるのが正しいです。 常に というのはaに値が加算される処理が必ず実行されないからこそ成り立つものであり BooleanとなったaにIntegerが加算されるとエラーになります。 ここも回答修正しておきますね。
退会済みユーザー

退会済みユーザー

2019/02/01 06:04

度々すみません、やっぱり最初の比較で代入されて2回目以降常にtureが返ってきました。 多分最初の説明が正しかったのかな...。 ただcase文の記述としてはおかしいことに変わりないので本来こういう書き方はしません。 自分が間違えて覚えていたのもあって、なぜtrueが毎回帰って実行されるのかについては すみません、ちょっとわかりません。
KentaTsujino

2019/02/01 06:08

詳しい解説ありがとうございました! 現在の自分の知識ではいまいち理解が追いつきませんでしたが、これから理解できるように頑張ります。
otn

2019/02/01 06:12

a=n というのは、a==n の書き誤りでは? a=nは比較じゃなくて代入ですよ。
退会済みユーザー

退会済みユーザー

2019/02/01 06:18

when a=n になっていた部分ですね。 > when a=n ###ここが常に出てきます。 混乱してましたがまとまりました。 if (a = n) === a の比較になるので、やはり最初の比較でnの値がaに代入されて 次回からは同じ値同士の比較になっています。
guest

0

ベストアンサー

whena < nのような一致でない条件判断を入れる場合、case aではなくcaseとだけしてください。caseだけの場合、whenの中で最初にtrue相当となったものが条件を満たします(るりま)。

もっとも、ふつうにif - elsif - elseなどを使ったほうがわかりやすいかもしれません。

投稿2019/02/01 04:48

maisumakun

総合スコア145183

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

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

KentaTsujino

2019/02/01 04:56

Caseの使い方に加えてほかのメソッドまで提案していただいてとても参考になりました。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問