MrWater
MrWater

Reputation: 1797

Case statement not working as expected

I have one single file called Exercises.rb

def ask(prompt)
  print prompt, ' '
  $stdout.flush
  s = gets
  return s
end

def myreverse(s)
  aux=""
  for i in 0..s.length-1
    aux=s[i] + aux
  end
  return aux
end

def mywordreverse(s)
  aux=[]
  s=s.split(" ")
  for i in 0..s.length-1
    aux.unshift(s[i])
  end
  return aux.join(" ")
end

def choose(s,option)
  case option
    when 1 then print myreverse(s)
    when 2 then print mywordreverse(s)
    when 3 then print "hello"
    else print "You gave me #{option} -- I have no idea what to do with that."
  end
end

s=ask("Write a string to reverse: ")
option=ask("Choose an option. 1 - Reverse string. 2 - Reverse String words : ")

choose(s,option)

I am always getting You gave MYCHOSENOPTION -- I have no idea what to do with that., no matter what option I choose. If I put an if just before the case comparing 1, it just doesn't seem to be matching the option to my strings.

Upvotes: 1

Views: 1047

Answers (2)

Phrogz
Phrogz

Reputation: 303251

FWIW, here is how I would write this program:

def ask(prompt)
  print "#{prompt} "
  gets.chomp
end

def myreverse(s)
  s.reverse
end

def mywordreverse(s)
  s.split(' ').reverse.join(' ')
end

def choose(s,option)
  case option
    when 1 then puts myreverse(s)
    when 2 then puts mywordreverse(s)
    when 3 then puts "hello"
    else        puts "You gave me #{option}; I don't know what to do with that."
  end
end

$stdout.sync
str    = ask("Write a string to reverse: ")
option = ask("Choose an option:\n1: Reverse string\n2: Reverse String words\n>")
choose(str,option.to_i)

Notes:

  1. The last expression in a method is the return value; using return is almost never needed or desirable in Ruby.
  2. There exist built-in methods for reversing strings and arrays. (I understand if you are doing this for an exercise.)
  3. It is cumbersome to iterate arrays or strings in Ruby using for. Instead, you should use

    my_str.each_char do |char|
      # use the single-character string `char` here
    end
    
    my_array.each do |item|
      # use the item here
    end
    
  4. You can use $stdout.sync to force output to always be flushed.

  5. You need to use chomp on your string to remove the trailing newline always included when the user presses Enter.
  6. As pointed out by @robbrit, the core of your problem is that the return value of gets is a String, and you are comparing it to a Fixnum. I've used to_i in my code above to convert the string to an integer for comparison.
  7. I've used puts instead of print for the output so that I get a newline at the end and do not leave the user with their next command prompt on the same line as the output.

Upvotes: 1

robbrit
robbrit

Reputation: 17960

Try this:

 case option.to_i
    # rest of your code...

In Ruby, 1 == "1" (or more specifically in the case of a case statement, 1 === "1") always evaluates to false. You'll need to convert one of them so that they are the same type before doing the comparison. The value that you're passing in for option is likely a String and will therefore fail for any comparisons to integers.

Upvotes: 2

Related Questions