I'm create some sample code and still begineer
class Number
def initialize(name)
#first = []
#second = []
#final = 0
end
def input
print "Please input first number"
#first = gets.chomp
print "Please input second number"
#second = gets.chomp
end
def output
#final = #first * #second
puts #final
end
end
number = Number.new('Jakz')
number.class
number.input
number.output
I want to sum the 2 input number but its give error because the 2 number become a string not a number.How to fix it?
gets returns a String. The prompt does not know that you are requesting a number. Calling to_f does its best to convert the string to a floating point number
def input
print "Please input first number"
#first = gets.chomp.to_f
print "Please input second number"
#second = gets.chomp.to_f
end
be aware that if the user enters something that is not a number - the above code does not validate it, and will most probably set the variables to 0.
Related
This code is supposed to update the total within the loop, but when I put the total when its broken it doesn't update.
total = 0
while true do
puts "Give me a number"
input = gets.chomp
if input == Integer
total += input
elsif input == "stop"
puts total
break
end
end
input = gets.chomp will result String class. So your logic on if input == Integer it will never be reached. you need to convert it to integer using to_i and input == Integer i never used that kind of syntax to check the classes, i rather use input.is_a?(String). but if you convert to integer first it will never check stop string condition. so maybe
total = 0
while true do
puts "Give me a number"
input = gets.chomp
if input == "stop"
puts total
break
end
total += input.to_i
end
As mentioned in the above comment by mu is too short and dedypuji's answer you have a couple of issue. Here is another variation that I think will work and I think is a little more ruby idiomatic.
total = 0
loop do
print "Give me a number: "
input = gets
break if /stop|^$/ =~ input
total += input.to_i
end
puts total
I wrote a code where it asks multiple individuals questions, and every individuals' response is put into a hash. This is in a loop and looks something like this
arr:[]
(1..n).each do |i|
hash=Hash.new()
puts "Please input a value for day # #{i}"
hash["day1"]=gets.chomp.to_f
puts "Please input a value for day # #{i}"
hash["day2"]=gets.chomp.to_f
arr << hash
end
So to avoid any incorrect input (i.e. entering string instead of an integer/number), I need to place a conditional statement.
I am super lost with how I would do that though since I am assigning the users' input into a hash at the same time I take their input.
Is it even possible to do that or should I take a different route completely.
thanks
You can get day values like below. When a character other than a number is entered, it asks the value of that day again.
puts 'Enter number of days'
days_hash = {}
number_of_days = gets.chomp.to_i
day = 1
while day <= number_of_days
puts "Please enter a value for day # #{day}"
input = gets.chomp
if input !~ /\D/
days_hash["day#{day}"] = input.to_i
day += 1
else
puts "Please enter only number"
next
end
end
p days_hash
#=> { "day1" => 2, "day2" => 4, "day3" => 8 }
days_hash['day2']
#=> 4
Maybe you can consider this general approach for validating user input, note that this example require 'date'.
So, you can check user input to be an integer or a float or a formatted date or anything you could add...
First define an array of questions containing the question text, validation method and way to convert the input, like this:
questions = [
{text: "Enter an integer:", validate: :must_be_an_integer, convert: :my_to_i},
{text: "Enter a float:", validate: :must_be_a_float, convert: :my_to_f},
{text: "Enter a data as d-m-yyyy", validate: :must_be_a_formatted_date, convert: :to_formatted_date}
]
Then define some methods to be called by :validate key, for user input validation:
def must_be_an_integer(num)
Integer(num).class == Integer rescue false
end
def must_be_a_float(num)
Float(num).class == Float && num.include?('.') rescue false
end
def must_be_a_formatted_date(date_str)
date = Date.strptime(date_str, "%d-%m-%Y") rescue false
return false unless date
date.year <= 9999 && date.year >= 1000
end
Define also the methods required by the key :convert (need to pass an argument, that's why my_to_i and my_to_f):
def my_to_i(num)
num.to_i
end
def my_to_f(num)
num.to_f
end
def to_formatted_date(date_str)
DateTime.strptime(date_str, "%d-%m-%y")
end
Finally iterate over the questions:
res = questions.map do |question|
answer = nil
3.times do
puts question[:text]
u_input = gets.chomp
if send question[:validate], u_input
answer = send question[:convert], u_input
break
end
end
if answer.nil?
puts "C'mon man! Check your keyboard!" # after three input errors!!
break
end
{ question: question[:text], answer: answer }
end
Example of a result:
#=> [
{:question=>"Enter an integer:", :answer=>1},
{:question=>"Enter a float:", :answer=>1.1},
{:question=>"Enter a data as d-m-Y", :answer=>#<DateTime: 2020-10-27T00:00:00+00:00 ((2459150j,0s,0n),+0s,2299161j)>}
]
I'm sure it would be hard to find an easier question, but I'm a complete newbie. I have searched extensively and for some reason can't find the answer to this. Here's my code:
puts "Enter F for Fahrenheit and C for Celsius."
x = gets.chomp.downcase
def ftoc(fahrenheit)
(fahrenheit.to_f - 32.0) * (5.0 / 9.0)
end
if x == "f"
puts "Enter your temp:"
temp = gets.chomp.to_i
ftoc temp
elsif x == "c"
puts "Enter your temp:"
temp = gets.chomp.to_i
ctof temp
else
puts "That does not compute."
end
I'm just trying to get the returned result of the method into a variable so I can use it elsewhere....
Remember that calls like ctof temp just initiate a method and then, as you're not putting the result anywhere, discard it immediately.
To clean up this code let's organize it better:
# Temperature conversion method
def ftoc(fahrenheit)
(fahrenheit.to_f - 32.0) * (5.0 / 9.0)
end
# User input method
def temperature_prompt!
puts "Enter F for Fahrenheit and C for Celsius."
x = gets.chomp.downcase
case (x)
when "f"
puts "Enter your temp:"
temp = gets.chomp.to_i
ftoc temp
when "c"
puts "Enter your temp:"
temp = gets.chomp.to_i
ctof temp
else
puts "That does not compute."
end
end
Now you can make use of the fact that in Ruby things like if and case actually return values. In this case it's the value of the last thing to execute in each block, so that result isn't discarded, it's just passed along:
temp = temperature_prompt!
If you enter an invalid value you get the result of puts which is conveniently nil.
Here's something to consider: Ruby is very good at parsing arbitrary text if you can describe the patterns. Here's a simple input routine:
def temperature_prompt!
puts "Enter degrees (e.g. 8F, 2C)"
case (input = gets.chomp.downcase)
when /(\d+)f/
ftoc $1
when /(\d+)c/
ctof $1
else
puts "That does not compute."
end
end
You could add to those patterns to allow things like -2C and 3.4°F if you wanted.
I would like the variable size to be defined in my program via user input. I have been unsuccessful in defining it in any way other than by a number manually entered into my code (currently 10).
def pass (size = 10)
This works for me:
def pass(size)
puts size
end
puts "please input a number:"
size = gets
pass(size)
You may need to use to_i, as your user input is a string. Then it works as the previous answer:
def pass(size = 10)
size = size.to_i
puts "It's a number! #{size}" if size.is_a? Integer
end
puts "please input a number:"
size = gets
pass(size)
I'm hoping to get my Ruby script to start at an inputted number, say 100, and itterate all the way up to the end of the range; 1000. Having all the numbers in between saved to a file.
This is a code I have so far:
#!/usr/bin/env ruby
if ARGV.length ==0;
puts "Enter the start number"
else puts ARGV.size
ARGV.each do |a|
for i in 0..1000 do
puts i;
end
end
end
To run it I'm typing:
ruby increment.rb 100 > increment.txt
However, it ignores the input number and starts at 1 regardless.
What am I doing wrong?
It starts at 0 because you're giving it the range 0..1000, which starts at 0. If you want to use the numeric value of a as the starting point, use a.to_i instead of 0.
ARGV is an array and the first argument is stored in ARGV[0] second in ARGV[1] etc
if ARGV[0]
start = ARGV[0].to_i
else
puts "Enter the start number"
start = gets.to_i
end
(start .. 1000).each do |i|
puts i
end