问题
I have made a simple calculator in ruby. However after running once the program stops and has to be re-run. I tried the following but it ended in an infinite loop. How can I write this so that it will run until the users tells it to quit?
puts "Please enter two digits separated by operation you would like to calculate:"
input = gets.chomp.split(' ')
while input != nil
if input[1] == "+"
puts input[0].to_i + input[2].to_i
elsif input[1] == "-"
puts input[0].to_i - input[2].to_i
elsif input[1] == "*"
puts input[0].to_i * input[2].to_i
else
puts input[0].to_i / input[2].to_i
end
end
回答1:
split(' ')
returns an array and not nil, so input != nil
always evaluates to true, which makes an infinite loop.
You may want to try while input.size == 2
, or break
the while loop at certain input like:
while true
# ... if / elsif for operators
elsif input[1] == 'exit'
break # end the 'while' loop
end
end
回答2:
make changes like below:
msg = "Please enter two digits separated by operation you would like to calculate:"
puts msg
while input = gets.chomp.split(' ')
if input[1] == "+"
puts input[0].to_i + input[2].to_i
elsif input[1] == "-"
puts input[0].to_i - input[2].to_i
elsif input[1] == "*"
puts input[0].to_i * input[2].to_i
else
puts input[0].to_i / input[2].to_i
end
puts msg
end
回答3:
This whole thing is a big mess of Ruby that can be drastically simplified by degrees. The key here is to apply the Ruby way to things and elegant solutions become immediately obvious.
Consider replacing that messy while
loop with an actual loop
structure. Also name the elements resulting from the split
based on their meaning to you:
loop do
puts "Please enter two digits separated by operation you would like to calculate:"
left, operator, right = gets.chomp.split(' ')
result = case (operator)
when '+'
left.to_i + right.to_i
when '-'
left.to_i - right.to_i
when '*'
left.to_i * right.to_i
when '/'
left.to_i / right.to_i
end
puts result
end
Now this looks like a lot of repetition, the only thing changing here is the operator. Since Ruby is a highly dynamic language we can actually collapse this some more:
loop do
puts "Please enter two digits separated by operation you would like to calculate:"
left, operator, right = gets.chomp.split(' ')
result = case (operator)
when '+', '-', '*', '/'
left.to_i.send(operator, right.to_i)
end
puts result
end
Now there's still some duplication here. What about trying to reduce this further and also allow for more flexibility:
loop do
puts "Please enter digits separated by the operations you would like to calculate:"
values = gets.chomp.split(' ')
while (values.length > 2)
left = values.shift.to_i
operator = values.shift
right = values.shift.to_i
values.unshift(left.send(operator, right))
end
puts values[0]
end
That means you can have arbitrarily long lists of numbers to add together. It's not much harder to make this tokenize your string into numbers and non-number components, but that's something you can try on your own.
回答4:
A recursive approach:
def recurs_calc
puts "Please enter two digits separated by operation you would like to calculate:"
input = gets.chomp.split(' ')
if input[1] == "+"
puts input[0].to_i + input[2].to_i
recurs_calc
elsif input[1] == "-"
puts input[0].to_i - input[2].to_i
recurs_calc
elsif input[1] == "*"
puts input[0].to_i * input[2].to_i
recurs_calc
elsif input[1] == '/'
puts input[0].to_f / input[2].to_i
recurs_calc
elsif input[0] == 'exit'
exit
else
puts 'please enter two numbers with SPACES i.e. 4 + 4 then enter'
recurs_calc
end
end
recurs_calc
Here we recall recurs_calc
as per conditions and exit when the user types 'exit'
. Note I've also used to_f
in the /
branch to get a more accurate result and included a final branch that takes into account an 'incorrect' input. Try running it.
Just another approach using eval
that you may find helpful although this is probably cheating a bit. Also it's considered bad practice to use eval
for security reasons. Also a special thanks to @nicael for the string substitution:
loop do
puts "Enter calculation"
input = gets.chomp
if input == 'exit'
exit
else
p eval (input.gsub(/(\d+)/, '\1.0'))
end
end
来源:https://stackoverflow.com/questions/38649405/making-ruby-calculator-run-continuously