From: Adam Bourg on 11 Jul 2010 12:34 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 Attachments: http://www.ruby-forum.com/attachment/4848/Screen_shot_2010-07-11_at_10.33.56_AM.png -- Posted via http://www.ruby-forum.com/.
From: Stefano Crocco on 11 Jul 2010 13:02 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
From: Rick DeNatale on 11 Jul 2010 13:05 On Sun, Jul 11, 2010 at 12:34 PM, Adam Bourg <adam.bourg89(a)gmail.com> wrote: > if ( age.to_f.to_s == true ) This will NEVER happen. age.to_f converts the string to a float. If the string isn't valid it returns 0.0. age.to_f.to_s will ALWAYS be a string, and will never == true > monthsold = age.to_i * months.to_i > puts 'You are ' + monthsold.to_s + ' months old' > else > Now I'm not sure whether or not you really want to accept an age as a float, or just an integer, but you need to do something else to validate the string. One way would be to use a regular expression, e.g. something like if age =~ /^d+$/ # for an integer or if age =~/^d+(|\.\d*)$/ # for a float These are fairly strict in what they'll accept, you might want slightly different regular expressions, particularly if you really want a float. Or use either Kernel#Integer or Kernel#Float which raise an error if they don't like the string: float_age = Float(age) rescue nil if float_age #.... HTH -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Github: http://github.com/rubyredrick Twitter: @RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale
From: Doc O'Leary on 11 Jul 2010 13:34 In article <c2a8f01abcd51484ec6a1704fda75ebb(a)ruby-forum.com>, Adam Bourg <adam.bourg89(a)gmail.com> wrote: > if ( age.to_f.to_s == true ) What do you expect this to evaluate to? Instead of "true", did you mean to use "age" (i.e., compare the original string with a reconverted number string)? Even that test will fail: irb(main):003:0> "42".to_f.to_s == "42" => false Barring full-blown input validation, the simple solution is to note that non-numbers get converted to 0. That also happens to be an age you can likely reject. Run with it. -- My personal UDP list: 127.0.0.1, localhost, googlegroups.com, astraweb.com, and probably your server, too.
From: Brian Candler on 11 Jul 2010 16:53 Rick Denatale wrote: > On Sun, Jul 11, 2010 at 12:34 PM, Adam Bourg <adam.bourg89(a)gmail.com> > wrote: >> if ( age.to_f.to_s == true ) > > This will NEVER happen. > > age.to_f converts the string to a float. If the string isn't valid it > returns 0.0. I'd use Float(age), which will raise an exception for invalid values. irb(main):001:0> Float("1") => 1.0 irb(main):002:0> Float("1.5") => 1.5 irb(main):003:0> Float("1.5 ") => 1.5 irb(main):004:0> Float("1.5 z") ArgumentError: invalid value for Float(): "1.5 z" from (irb):4:in `Float' from (irb):4 from :0 > Now I'm not sure whether or not you really want to accept an age as a > float, or just an integer, but you need to do something else to > validate the string. > > One way would be to use a regular expression, e.g. something like > > if age =~ /^d+$/ # for an integer except that particular regexp allows strings which are not just numbers, e.g. >> age = "foo\n123\nbar" => "foo\n123\nbar" >> puts "oops" if age =~ /^\d+$/ oops => nil Use \A and \z to match start and end of the string. > or > if age =~/^d+(|\.\d*)$/ # for a float except that particular regexp allows invalid floats (e.g. "1.") and disallows valid ones (e.g. "1.0e5") Using regexps to validate data is perfectly reasonable, just be very careful that the regexp you write matches exactly what you expect and nothing else. > Or use either Kernel#Integer or Kernel#Float which raise an error if > they don't like the string: > > float_age = Float(age) rescue nil > if float_age > #.... Beware that Integer() handles values which start with zero as octal. >> "0100".to_i => 100 >> Integer("0100") => 64 -- Posted via http://www.ruby-forum.com/.
|
Next
|
Last
Pages: 1 2 Prev: What does this mean? Next: Basic Question: How do you check to see if gets is a num |