2016-04-16 50 views
0

下面的代码创建一个记忆所有操作数和操作符的计算器。“Evaluate”函数接收一个Ops数组并返回一个包含结果和剩余操作的元组。但我无法理解交换机出现了什么问题。return语句如何在switch中工作?

如果情况是opStack有4个x,5,+,6最后一个元素6在开关中被删除并检查。由于它是一个操作数,它将返回6(操作数),剩下的元素4,x,5,+。

我的理解是否正确? “6”和“4,x,5,+”去哪里以及整个表达如何评估?

  private enum Op { 
    case Operand (Double) 
    case UnaryOperation(String , Double -> Double) 
    case BinaryOperation(String , (Double,Double) -> Double) 
     } 
private var opStack = [Op]() 
private var knownOps = [String : Op]() 

init() { 
    knownOps["×"] = Op.BinaryOperation("×" , *) 
    knownOps["÷"] = Op.BinaryOperation("÷"){ $1/$0 } 
    knownOps["+"] = Op.BinaryOperation("+" , +) 
    knownOps["−"] = Op.BinaryOperation("−"){ $1 - $0 } 
    knownOps["√"] = Op.UnaryOperation("√" ,sqrt) 
} 

    private func evaluate(ops : [Op]) -> (result : Double? , remainingOps: [Op]){ 

    if !ops.isEmpty { 
     var remainingOps = ops 
     let op = remainingOps.removeLast() 

     switch op{ 

     case .Operand(let operand): 
      return (operand , remainingOps) 

     case .UnaryOperation(_ , let operation): 
      let operandEvaluation = evaluate(remainingOps) 
     if let operand = operandEvaluation.result{ 
      return (operation(operand), operandEvaluation.remainingOps) } 

} 
     case .BinaryOperation(_, let operation): 
      let op1Evaluation = evaluate(remainingOps) 
      if let operand1 = op1Evaluation.result { 
       let op2Evaluation = evaluate(op1Evaluation.remainingOps) 
       if let operand2 = op2Evaluation.result { 
        return (operation(operand1, operand2), op2Evaluation.remainingOps) 
       } 
      } 
     } 
      } 
    return(nil , ops) 
} 
+1

函数是递归的;请注意'UnaryOperation'和'BinaryOperation'事件调用'evaluate'。你可以在函数中设置一个断点和一步,看看它是如何工作的,但是当你说操作数堆栈里有'4,x,5,+,6'时,我怀疑你是不正确的。它看起来会有两个操作“4x5”和“+6” – Paulw11

回答

0

啊你在做斯坦福大学的快速讲座!他们都是伟大的。当我经历他们时,我也遇到了这个函数的一些问题。

基本上,计算器在工作方式上非常不典型,需要一点时间才能正确使用它作为用户。调用堆栈将返回6,在这种情况下,你是绝对正确的。然后用户可以再次评估,但是您的调用堆栈无法正常工作。

计算器期望该流为一个二进制运算:

用户输入操作数1,并将其添加到堆栈 用户输入操作数,并将其添加到堆栈中。 然后将用户输入的二进制运算符,他们想申请到操作数

所以对于二进制操作的调用堆栈看起来是这样的:

[5,6,*]

这将评估至30

对于一元运算预计:

用户输入操作数,并把它添加到堆栈 用户选择的一元运算他们想应用到操作数

所以一元调用堆栈的样子:

[4√]

这将评估2

是这样工作的,在没有操作的操作之前它在栈会结束评估运行,否则它不会理解堆栈的其余部分(看看你的堆栈,并将其与计算器的期望相比较,你会明白我的意思)

也像@ paulw11我会高度建议设置一个布雷阿kpoint在开始时评估并逐步运行(非常缓慢),让您了解它的工作原理非常有用。

+0

谢谢,这有助于。 Y) – 209135