1

How do I write code to fore a user to enter a certain value type such as an int, and then force or loop a prompt until a user enters an int, rather than a string or numbers with string characters? I am thinking some type of Boolean with for or while loop.

sawa
  • 165,429
  • 45
  • 277
  • 381
Jarg
  • 33
  • 4
  • 2
    Welcome to stackoverflow. Please show what you have tried, what doesn't work with your approach (e.g. error messages, what exactly doesn't work, ...) and what you tried to fix the issue. Please edit your question with the additional information. – Holger Just Mar 12 '14 at 07:51

1 Answers1

2

Let's start with some basics. Put this into a file userinput.rb:

print "Please enter a number: "
input = gets
puts input

Then run with ruby userinput.rb. You get a prompt and the program outputs whatever you type in.

You want your input to be an integer, so let's use Integer() to convert the input:

print "Please enter a number: "
input = gets
puts Integer(input)

Type in an integer and you'll get an integer output. Type in anything else and you'll get something like this:

userinput.rb:3:in `Integer': invalid value for Integer(): "asdf\n" (ArgumentError)
        from userinput.rb:3:in `<main>'

Now you can build a loop that prompts the user until an integer is typed in:

input = nil # initialize the variable so you can invoke methods on it
until input.is_a?(Fixnum) do
  print "Please enter a number: "
  input = Integer(gets) rescue nil
end

The interesting part is input = Integer(gets) rescue nil which converts the integer and, in case of an ArgumentError like above, the error gets rescued and the input var is nil again.

A more verbose way of writing this (except that this catches only ArgumentError exceptions) would be:

input = nil # initialize the variable so you can invoke methods on it
until input.is_a?(Fixnum) do
  print "Please enter a number: "
  begin
    input = Integer(gets)
  rescue ArgumentError # calling Integer with a string argument raises this
    input = nil        # explicitly reset input so the loop is re-entered
  end
end

Some notes:

  1. Please don't get confused by Integer and Fixnum. Integer is the parent class that also encapsulates big numbers, but it's fairly standard to test for Fixnum (as in the loop head). You could also just use .is_a?(Integer) without changing the behavior.
  2. Most Ruby tutorials probably use puts over print, the latter's output doesn't end with a newline, which makes the prompt appear in one line.
awendt
  • 13,195
  • 5
  • 48
  • 66
  • Thanks very much, helpful. I don't really understand the code as far as fixnum up till the rescue nil, is there a place you would recommend I could read up to better grasp the until loop and fixnum. Also, You can use the gets method inside the integer class? – Jarg Mar 12 '14 at 20:23
  • `gets` is just a method that always returns a string. If you enter `asdf`, it will call `Integer("asdf")`, If you enter a number like `23`, it will call `Integer("23")`. The `Integer()` part is not a class but a function. I'm well aware this must be confusing, I'd advise you to run `irb` and play around in that prompt to get the concept. See also this on SO: http://stackoverflow.com/a/49282/473467 – awendt Mar 13 '14 at 07:50
  • I'd also recommend to read up on loops in Ruby, a Google search will get you further here. I've edited my answer to give a more verbose example. – awendt Mar 13 '14 at 07:56
  • I see. And so essentially you are using the gets method inside of the integer method.So what exactly does that make 'Fixnum' is that a class then? I'm having trouble understanding the structure of ruby language. Do you have skype? Please add me or username: jarggsx – Jarg Mar 13 '14 at 08:19