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
Related
I am trying to loop until user inputs an integer. When user inputs a letter, the following code should print "Think of a number":
print "Think of a number "
while user_input = gets.to_i
if user_input.is_a? Integer
puts "your number is #{user_input}"
break
else
print "Think of a number "
end
end
I succeeded with my code when user inputs an integer. However when user inputs a string, the to_i method returns 0, and does not execute the else statement because it is a number.
The main issue with your code is String#to_i method is omnivorous.
"0".to_i #⇒ 0
"0.1".to_i #⇒ 0
"foo".to_i #⇒ 0
That said, user_input in your code is always integer.
What you probably want is to accept digits only (and maybe a leading minus for negatives.) The only concise way to accept a subset of characters is a regular expression.
# chomp to strip out trailing carriage return
user_input = gets.chomp
if user_input =~ /\A-?\d+\z/
...
The regular expression above means nothing save for digits with optional leading minus.
Or, even better (credits to #Stefan)
if gets =~ /\A-?\d+\Z/
If you only want to accept postive digits, you can use a range:
user_input = gets.chomp
if ('0'..'9').cover? user_input
let check below one used Integer(gets.chomp) rescue ''
print "Think of a number "
while user_input = Integer(gets.chomp) rescue ''
if user_input.is_a? Integer
puts "your number is #{user_input}"
break
else
print "Think of a number "
end
end
I came across a similar problem. I ended up doing this:
if user_input.strip == user_input.to_i.to_s
# More code here!
end
Testing for float would be:
if user_input.strip == user_input.to_f.to_s
# More code here!
end
Solved my issue. See if it helps.
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 am planning to check if a given input is an integer. gets.chomp gets input as a string, and I convert it into an integer using to_i. If I input abcd and check using class or is_a(Integer), it always says it's an integer.
x = gets.chomp.to_i
if x.is_a?(Integer)
puts "It's an integer"
else
puts "It's a string"
end
How can I check whether the input is an integer or a string?
Your problem
Since you're using .to_i to convert your input to an integer, x.is_a?(Integer) is always true, even when you have a string that does not contain any digit. See this answer for more information about .to_i's behavior.
Solution
Convert your input with Integer() instead of .to_i.
Integer() throws an exception when it cannot convert your input to an integer, so you can do the following:
input = gets.chomp
x = Integer(input) rescue false
if x
puts "It's an integer"
else
puts "It's a string"
end
You can use a regex:
boolean = gets.match?(/\A\d+\n\z/)
Another approach could be:
x = gets.chomp
x === x.to_i ? "It's an integer" : "It'a a 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
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.