I am new to Ruby. My past is in Java. I am trying to use a switch case, apparently known as a case expression in Ruby. I want to accept user input, check that input to see if it includes certain characters, and then substitute those characters with other characters. When I try to run this simple program I get many syntax errors but I am not sure why. Could someone please explain to me if I am using this statement wrong and if I can even use case expression in this situation? Thank you.
empty_string = true
while empty_string do
print "Pleathe enter a thtring: "
user_input = gets.chomp
user_input.downcase!
case
when user_input.include? ("s")
user_input.gsub!(/s/, "th")
when user_input.include? ("ch")
user_input.gsub!(/ch/, "th")
when user_input == ""
puts "You typed noting! You get nothing sir!"
when user_input != ""
empty_string = false
else
puts "There are no 's's in your string."
end
end
puts "Zai jian, #{user_input}"
Below are the errors correlating by line and syntax error
rb.rb:9: syntax error, unexpected ( arg, expecting keyword_then or ',' or ';' or '\n'
when user_input.include? ("s")
rb.rb:11: syntax error, unexpected keyword_when, expecting keyword_end
when user_input.include? ("ch")
^
rb.rb:13: syntax error, unexpected keyword_when, expecting keyword_end
when user_input == ""
^
rb.rb:15: syntax error, unexpected keyword_when, expecting keyword_end
when user_input != ""
^
rb.rb:17: syntax error, unexpected keyword_else, expecting keyword_end
rb.rb:21: syntax error, unexpected keyword_end, expecting end-of-input
BELOW IS THE FIXED CODE THANKS TO #Phlip
empty_string = true
while empty_string do
print "Pleathe enter a thtring: "
user_input = gets.chomp
user_input.downcase!
case
when user_input.include?("s")
user_input.gsub!(/s/, "th")
empty_string = false
when user_input.include?("ch")
user_input.gsub!(/ch/, "th")
empty_string = false
when user_input == ""
puts "You typed noting! You get nothing sir!"
empty_string = true
else
puts "There are no 's's in your string."
end
end
puts "Zai jian, #{user_input}"
The issue was the spaces I had after .include?, #Phlip told me Ruby is space sensitive. I removed the white space and it worked. I ran into an issue with the boolean after and fixed that as well. It works as intended now.
My understanding is that you wish to ask the user for a string until the string contains "s" or "ch". When such a string is found you wish to make one or more substitutions in the string and print out a string containing the modified string. Here is a Ruby-like way of doing that.
user_input = nil
loop do
print "Pleathe enter a thtring: "
user_input = "cheater" # gets.chomp.downcase
case user_input
when /s/
user_input.gsub!('s','th')
break
when /ch/
user_input.gsub!('ch','th')
break
when ""
puts "You typed noting! You get nothing sir!"
else
puts "There are no 's's in your string."
end
end
puts "Zai jian, #{user_input}"
If the user enters an empty string, "You typed noting! You get nothing sir!" and then "Pleathe enter a thtring: " are displayed and gets awaits another entry.
If the user enters a non-empty string that contains no "s"'s or "ch"'s, "Pleathe enter a thtring: " is displayed and gets awaits another entry.
If the user enters "Chester\n" "Zai jian, chethter" is diplayed.
If the user enters "Cheater\N" "Zai jian, theater" is displayed.
If you actually wish to replace all "s"'s and "ch"'s, substitute the following for the first two when statements.
when /s|ch/
user_input.gsub!(/s|ch/,'th')
break
If this is done and user enters "Chester" "thethter" is displayed. (The when line could instead be written when /s/, /ch/, but I don't like that as well, in part because /s|ch/ is still needed as gsub!'s first argument.)
Note that case statements use the method Regexp#===. We therefore see that /s/.===(s) #=> true. Ruby allows us to write that /s/ === 'chester' ("syntactic sugar").
user_input = <anything> must precede the loop to make its value visible after the loop.
See Kernel#loop. For other uses of this method the handling of StopIteration exceptions is very useful when working with enumerators (instances of the Enumerator class).
=== looks a lot like ==, but they should be thought of as entirely different methods.
Related
I want in brief to run a program to check if the user input is empty to let him reinsert the needed data and in case there is "s" in the string to be substituted with another letter
print "Please enter a string: "
user_input = gets.chomp.downcase!
if user_input.empty?
print "Please enter a vaild string... "
user_input = gets.chomp.downcase!
elsif
user_input.include? "s"
user_input.gsub!(/s/, "th")
else
puts "There are no 's's in your string. #{user_input}"
end
puts "Your new thtring is #{user_input}."
The problem is with this line
user_input = gets.chomp.downcase!
according to the docs
Downcases the contents of str, returning nil if no changes were made.
So if the user inputs a string with only lowercase letters, nil is returned.
Your function works if a user enters FOO, then it works fine.
You're better off using downcase instead of downcase!. downcase always return the string itself.
As I understand you need get valid user input (with s)
Now you are only using if and this does not guarantee that user input will be valid
You can refactor to something like this
puts "Please enter a string with s:"
thtring = ""
loop do
user_input = gets.chomp
next puts "Please enter some string..." if user_input.empty?
thtring = user_input.downcase
next puts "There are no 's's in your string" unless thtring.include?("s")
break thtring.gsub!(/s/, "th")
end
puts "Your new thtring is #{thtring}."
I'm trying to loop this question until the user's input is a string value:
Question: What is your name?
I don't want the user to just press enter and leave the name blank.
I don't want the user's input to be numeric/numbers.
Please see my code below:
name1 = gets.chomp.to_s
loop do
print "Please enter your name "
name1 = gets.chomp.to_s
if name1.empty?
puts "No input."
else name1.to_i
puts "Illegal character ':'"
end
end
With this code, I can't proceed to the next question even if I input a string value. Please help.
Your code has several issues:
Your input and output is out of order. You gather input before prompting and that input (from your first line) is never used:
name1 = gets.chomp.to_s # <- Ruby is waiting for input
loop do
print "Please enter your name " # <- user is prompted to enter name
name1 = gets.chomp.to_s # <- previous input is overwritten
# ...
end
The first line should probably be deleted.
gets might return nil, but chomp always returns a string. Calling to_s afterwards is therefore superfluous.
Your if-else construct is actually:
if name1.empty?
puts "No input."
else
name1.to_i
puts "Illegal character ':'"
end
So whenever the input is not empty?, you convert it to an integer (discarding the result) and print an error message. You probably want an elsif instead (/.../ is a regexp and \d matches a digit):
if name1.empty?
puts 'No input.'
elsif name1.match? /\d/
puts 'Digits not allowed.'
end
You could also use a case expression:
case name1
when ''
puts 'No input.'
when /\d/
puts 'Digits not allowed.'
end
You never break out of your loop. The code keeps looping even if no error was found. This can be fixed by adding a break statement in an else branch (to either if or case):
# ...
else
break
end
gets.chomp will always return a string, and as such there is no need to call to_s on the method.
If you don't want the user to be able to input any integers, you could use the following for a clean solution:
name.count("0-9") > 0
If this returns true, then you know that the user's input contains at least one number.
I need to check whether my variable is an Integer or a String.
The code below will just break the loop, without warning me for an illegal character. Can anyone help me to find the mistake?
x = 0
while x == 0
name = gets.chomp.capitalize
if name.empty?
puts "No input. Try again"
elsif name.is_a? Integer
puts "Illegal character: Integer "
else
x = 1
end
end
Because gets returns a string you need to find out if the string represents a number (and only a number).
First, translate your string to an integer with to_i. Please note that to_i returns 0 for strings that do not include numbers. In a second step check if translating this integer back into a string matches the original string
string.to_i.to_s == string
Note that this is just a simple example, it wouldn't work for example with the string 00.
Another way might be checking if the string only contains numbers. That could be done by using a regexp:
string.match(/\A\d+\z/)
You can do something like this:
loop do
puts "Enter name"
name = gets.chomp
if name.empty?
puts "No input, try again"
elsif name.scan(/\d+/).any?
puts "Illegal character: Integer"
else
raise StopIteration
end
end
case-expression
Or use a case-expression to tidy things up.
loop do
puts "Enter name"
case gets.chomp
when ''
puts "No input, try again"
when /\d/
puts "Illegal character: Integer"
else
raise StopIteration
end
end
See String#scan, Array#any? and StopIteration for further details
I need to check whether my variable is an Integer or a String.
The code below will just break the loop, without warning me for an illegal character. Can anyone help me to find the mistake?
x = 0
while x == 0
name = gets.chomp.capitalize
if name.empty?
puts "No input. Try again"
elsif name.is_a? Integer
puts "Illegal character: Integer "
else
x = 1
end
end
Because gets returns a string you need to find out if the string represents a number (and only a number).
First, translate your string to an integer with to_i. Please note that to_i returns 0 for strings that do not include numbers. In a second step check if translating this integer back into a string matches the original string
string.to_i.to_s == string
Note that this is just a simple example, it wouldn't work for example with the string 00.
Another way might be checking if the string only contains numbers. That could be done by using a regexp:
string.match(/\A\d+\z/)
You can do something like this:
loop do
puts "Enter name"
name = gets.chomp
if name.empty?
puts "No input, try again"
elsif name.scan(/\d+/).any?
puts "Illegal character: Integer"
else
raise StopIteration
end
end
case-expression
Or use a case-expression to tidy things up.
loop do
puts "Enter name"
case gets.chomp
when ''
puts "No input, try again"
when /\d/
puts "Illegal character: Integer"
else
raise StopIteration
end
end
See String#scan, Array#any? and StopIteration for further details
I am creating a Daffy Duck speech converter (Very simple. Straight from CodeCademy) and I am having an issue with displaying the modified entry from the user.
Code:
puts "What would you like to convert to Daffy Duck language?"
user_input = gets.chomp
user_input.downcase!
if user_input.include? "s"
user_input.gsub!(/s/, "th")
print #{user_input}
else puts "I couldn't find any 's' in your entry. Please try again."
end
It will change any 's' in your entry to a 'th', therefore, making it sound like a Daffy Duck once read aloud. When I enter it into the interpreter, it will not display the modified string. It will just display the original entry by the user.
EDIT:
Thanks to the users below, the code is fixed, and I added a notice to the user with converted text. Thanks guys!
A # outside a string starts a comment, so #{user_input} is ignored, i.e.
print #{user_input}
is equivalent to
print
You might wonder why a single print outputs the original input. This is because without arguments print will print $_. That's a global variable which is set by gets:
user_input = gets.chomp # assume we enter "foo"
user_input #=> "foo"
$_ #=> "foo\n"
Everything works as expected if you pass a string literal:
print "#{user_input}"
or simply
print user_input
Note that gsub! returns nil if no substitutions were performed, so you can actually use it in your if statement:
if user_input.gsub!(/s/, "th")
print user_input
else
puts "I couldn't find any 's' in your entry. Please try again."
end
You just need to add double quotes around the string interpolation. Otherwise your code was just returning the input.
puts "What would you like to convert to Daffy Duck language?"
user_input = gets.chomp
user_input.downcase!
if user_input.include? "s"
user_input.gsub!(/s/, "th")
print "#{user_input}"
else
puts "I couldn't find any 's' in your entry. Please try again."
end
You don't even need interpolation, actually. print user_input works. Notice how StackOverflow was even syntax highlighting your code as a comment. :)