【问题标题】:Making ruby calculator run continuously使 ruby​​ 计算器连续运行
【发布时间】:2016-12-03 14:46:13
【问题描述】:

我用 ruby​​ 做了一个简单的计算器。但是,一旦程序停止运行,就必须重新运行。我尝试了以下方法,但它以无限循环结束。我该如何编写它才能运行直到用户告诉它退出?

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

【问题讨论】:

  • input 永远不会是 nil,它始终是一个数组。请注意,在 Ruby 中x != nil 实在是太混乱了,99% 的时间while x 都可以。唯一逻辑错误的是falsenil。空数组、空字符串、0等都是真实的。

标签: arrays ruby while-loop calculator


【解决方案1】:

split(' ') 返回一个数组而不是 nil,所以input != nil 总是计算为真,这会产生一个无限循环。

您可能想在特定输入处尝试while input.size == 2break while 循环,例如:

while true
  # ... if / elsif for operators
  elsif input[1] == 'exit'
    break # end the 'while' loop
  end
end

【讨论】:

    【解决方案2】:

    递归方法:

    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
    

    这里我们根据条件调用recurs_calc,并在用户输入'exit'时退出。注意我还在/ 分支中使用了to_f 以获得更准确的结果,并包含一个考虑“不正确”输入的最终分支。尝试运行它。


    使用eval 的另一种方法可能对您有所帮助,尽管这可能有点作弊。出于安全原因,使用eval 也被认为是不好的做法。还要特别感谢 @nicael 的字符串替换:

    loop do
    puts "Enter calculation"
    input = gets.chomp
      if input == 'exit'
        exit
      else
        p eval (input.gsub(/(\d+)/, '\1.0'))
      end
    end
    

    【讨论】:

      【解决方案3】:

      进行如下更改:

      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
      

      【讨论】:

        【解决方案4】:

        这整件事是一大堆 Ruby,可以逐步简化。这里的关键是将 Ruby 方法应用到事物中,优雅的解决方案立即变得显而易见。

        考虑用实际的loop 结构替换那个凌乱的while 循环。还要根据它们对您的含义命名来自split 的元素:

        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
        

        现在这看起来有很多重复,这里唯一改变的是操作符。由于 Ruby 是一种高度动态的语言,我们实际上可以进一步折叠它:

        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
        

        现在这里还有一些重复。尝试进一步减少这种情况并提供更大的灵活性怎么样:

        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
        

        这意味着您可以将任意长的数字列表加在一起。将您的字符串标记为数字和非数字组件并不难,但您可以自己尝试。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-18
          相关资源
          最近更新 更多