Accept only numeric input - ruby

I want to force user to enter only numeric value from console. Below is my piece of code that is supposed to do that.
puts "Enter numeric value: "
result = gets.chomp
if result.to_i.is_a? Numeric
puts "Valid input"
else
puts "Invalid input."
end
It prints Valid input even if I enter a string value. And the reason is that every string has some equivalent numeric value in Ruby. Can someone help me fix the condition properly so that when user enters a non-numeric value, the script prompts Invalid input.?

to_i will convert any string to an integer, even if it shouldn't:
"asdf".to_i
which returns 0.
What you want to do is:
puts "Enter numeric value: "
result = gets.chomp
begin
result = Integer(result)
puts "Valid input"
rescue ArgumentError, TypeError
puts "Invalid input."
# handle error, maybe call `exit`?
end
Integer(some_nonnumeric_string) throws an exception if the string cannot be converted to an integer, whereas String#to_i gives 0 in those cases, which is why result.to_i.is_a? Numeric is always true.

Try regular expressions, like this:
puts "Enter numeric value: "
result = gets
if result =~ /^-?[0-9]+$/
puts "Valid input"
else
puts "Invalid input."
end
The example above allows only digits [0..9].
If you want to read not only integers, you can allow a dot as well: ^-?[0-9]+$/. Read more about regexp in Ruby: http://ruby-doc.org/core-2.2.0/Regexp.html

If you mean integer by "numeral", then:
puts "Enter numeric value: "
result = gets.chomp
case result
when /\D/, ""
puts "Invalid input"
else
puts "Valid input."
end
It also takes care of empty strings, which would be turned into 0 by to_i, which you probably do not want.

Related

What is wrong here in this Ruby Program?

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}."

Using regex in simple if statements?

Instead of doing:
puts "what type of input?"
input = gets.chomp
if %W[Int INT i I Ints ints].include?(input)
puts "enter int"
i = gets.to_i
I want to use regex to interpret string user input. For example,
puts "are you entering in a string, an int or a float?"
case gets
when /\A(string|s)\z/i
puts "enter in a string"
gets.chomp
when /\A(int|i)\z/i
puts "enter an int"
gets.to_i
when /\A(float|f)\z/i
puts "enter a float"
gets.to_f
end
What is the syntax in order to get the same result but using if statements instead of case statement?
gets returns a string with a trailing carriage return. What you need is to match the ending against \Z, not \z.
puts "are you entering in a string, an int or a float?"
case gets
when /\As(tring)?\Z/i
puts "enter in a string"
gets.chomp
when /\Ai(nt)?\Z/i
puts "enter an int"
gets.to_i
when /\Af(loat)?\z/i
puts "enter a float"
gets.to_f
else puts "Didn’t work"
end
I also slightly updated regexps to clearly show the intent.
If you want to turn your case into an if, you have to store the expression intended for the gets into a variable:
response=gets.chomp
if /..../ =~ response
...
elsif /.../ =~ response
....
....
else
...
end

Loop until answer is a string

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.

Ruby detects variable is string, but ends the script without breaking loop [duplicate]

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

Check whether my variable is an Integer or String

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

Resources