Making ruby calculator run continuously

橙三吉。 提交于 2021-01-29 02:16:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!