Duke II
Duke II

Reputation: 13

Can I recall the "case" in case?

I want to recall the case until user writes a or b. I do not want to use "case" particularly.

I just want to get input from user but not geting something else. If he writes something else, he should need to write until he writes a or b.

str = gets.chomp.to_s
case str
when "a"
    print "nice a"
when "b" 
    puts "nice b"
else 
    puts "please do it again"
end 

class person
 attr_accessor :name , :surname #and other attributes
end

#There will be a method here and it will run when the program is opened.
#The method will create the first object as soon as the program is opened. 
#The new object that the user will enter will actually be the 2nd object.

puts "What do you want to do?
add
list
out"

process = gets.chomp.to_s

case process
when "add"
    #in here user will add new objects of my class
when "list" 
    #in here user will show my objects
when "out"
    puts "Have a nice day"
else 
    puts "please do it again"   
end

In fact, if you look at it, many actions will be taken as a result of the user entering the correct input. what I want to tell is more detailed in this example. According to the input of the user, there will be actions such as calling methods, adding objects, etc.

I wrote most of the code on my computer. But still I couldn't solve my first problem.

Upvotes: 1

Views: 89

Answers (2)

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84413

Use Kernel#loop

There are a lot of ways to solve this problem, but let's start with a simple Kernel#loop wrapper around your existing code, as that's probably the easiest path forward for you.

loop do
  str = gets.chomp.to_s
  case str
  when "a"
    print "nice a"
  when "b"
    puts "nice b"
  else
    puts "please do it again"
    # restart your loop when not "a" or "b"
    next
  end
  # exit the loop if else clause wasn't triggered
  break
end

Use until Control Expression

The loop construct above is pretty straightforward, but it requires you to think about where you need next and break statements for flow control. My own instinct would be to simply call a block until it's truthy. For example, the core logic could be shortened to:

str = nil; until str =~ /a|b/i do str = gets.chomp end; p str

This is a lot shorter, but it's not particularly user-friendly. To leverage this approach while making the solution more communicative and error-resistant, I'd refactor the original code this way:

# enable single-character input from console
require 'io/console'

# make sure you don't already have a value,
# especially in a REPL like irb
str = nil

until str =~ /a|b/ do
  printf "\nLetter (a, b): "
  str = STDIN.getch.downcase
end

puts "\nYou entered: #{str}"

While not much shorter than your original code, it handles more edge cases and avoids branching. It also seems less cluttered to me, but that's more a question of style. This approach and its semantic intent also seem more readable to me, but your mileage may legitimately vary.

See Also

Upvotes: 1

BobRodes
BobRodes

Reputation: 6165

"I just want to do something until something else happens" is when you use some sort of while loop.

You can do this:

while true
  str = gets.chomp
  break unless str == 'a' || str == 'b'  
  puts "please do it again"
end 

You can also use loop do:

loop do
  str = gets.chomp
  break unless ['a', 'b'].include?(str) 
  puts "please do it again"
end 

puts "Nice #{str}."

Rubyists tend to prefer loop do over while true. They do pretty much the same thing.

One more thing. There's a simpler way to write out arrays of strings:

loop do
  str = gets.chomp
  break unless %w(a b).include?(str) 
  puts "please do it again"
end 

puts "Nice #{str}."

It doesn't look a whole lot simpler, but if you have, say, 10 strings, it's definitely quicker to type in when you don't have to use all those quotation marks.

As your intuition was telling you, you don't need to use the case statement at all. Like trying to kill a flea with a sledgehammer. The most concise way to do your check is to check whether the input character is included in an array of the desired characters.

Upvotes: 1

Related Questions