From: Stefano Crocco Date: 2010-07-12T02:02:48+09:00 Subject: Re: Basic Question: How do you check to see if gets is a number? On Sunday 11 July 2010, Adam Bourg wrote: > |I wrote a basic script that asks for your age then converts it into > |months, days and weeks old. I wanted to add some sort of control so that > |it would return an error if you didn't enter a number but rather a word > |or a letter or something. > | > |Can you please give me pointers? I've done quite a bit of Googling and > |am not sure how to do this. When I enter a number or a letter it > |returns the else statement. Please help! See attached for example of it > |being run. > | > |Here's my script below: > | > |# Basic Program to ask for a persons age and out put that in months > |# Writen by Adam Bourg on 2010-07-11 > | > |# Define verables > |months = 12 > | > |# Question that asks for your age > |puts "Hello, in the field below please enter your age:" > | > |# Get's is the ruby method that asks for your age, it gets the > |information from # the terminal when you type > |age = gets > | > |# This checks to see if you input a number, if you do it outputs the > |results > |# if you don't it asks you for it in a numerical format eg 21 > |if ( age.to_f.to_s == true ) > | monthsold = age.to_i * months.to_i > | puts 'You are ' + monthsold.to_s + ' months old' > |else > | puts 'Error, please enter a number!' > | end > | There are a couple of errors in your code. First of all, in ruby you never compare something with true (or false) in an if. That's because the only value which is == to true is... true (and the only value which is == to false is false). This explains why you keep getting the error message: you're comparing the string returned by the to_s method with true. These are different, so the == operator returns false, which leads to executing the "else" branch of the if. The if statement in ruby works in the following way: it checks what value the condition evaluates to. If it's the *false* object or the *nil* object, then the "else" branch is executed. All other values cause the "if" branch to be executed. So, to test whether a condition is true, you simply write: if some_expression ... else ... end where some_expression is any piece of ruby code which doesn't evaluate to false or nil. The first step to fix your code, then, is to remove everything left to the to_s inside the condition. You can also remove the brackets, as they're not needed around the condition in an if statement. This leaves us with: if age.to_f.to_s Now, the to_s method of any object will return a string which ruby will always consider a true value. This means that now we have the opposite problem we had before: the error message is never shown. Removing the to_s would help if String#to_f didn't return 0.0 (which is also considered a true value) in case the string doesn't represent a number. The simplest way to tell whether a string represents a number is to use the Kernel#Float method, or Kernel#Integer if you want an integer number. Unlike String#to_f and String#to_i, which always return a number, these methods raise an exception if the string can't be translated to a number. So you can write: #gets returns the string with a trailing newline, so you have to remove it age = gets.strip age_numeric = begin Integer(age) rescue ArgumentError puts "Enter a valid number" exit end #months is already an integer, so there's no need to call to_i on it monthsold = age_numeric * months I hope this helps Stefano