下面的代码创建了一个计算器,它会记住所有操作数和运算符。“Evaluate”函数接受一个 Ops 数组并返回一个包含结果和剩余操作的元组。但是我无法理解 switch 的情况.
如果情况是 opStack 有 4,x,5,+,6 最后一个元素 6 被删除并在 switch 中检查。由于它是一个操作数,它将返回 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)
}
最佳答案
啊,你正在做斯坦福大学的快速讲座!他们都是伟大的。当我使用这个函数时,我也遇到了一些问题。
基本上,该计算器的工作方式非常不典型,用户需要一些时间才能正确使用它。在这种情况下,调用堆栈将返回 6,你是绝对正确的。然后用户可以再次评估,但是您的调用堆栈将无法正常工作。
计算器期望此流程用于二元运算:
用户输入操作数1并将其添加到堆栈中 用户输入操作数2并将其添加到堆栈中。 然后用户输入他们想要应用于操作数的二元运算符
因此,二元运算的调用堆栈如下所示:
[5,6,*]
计算结果为 30
对于一元运算,它期望:
用户输入操作数并将其添加到堆栈中 用户选择他们想要应用于操作数的一元运算
所以一元调用堆栈看起来像:
[4,√]
计算结果为 2
它以这种方式工作,其中堆栈中前面没有操作的操作数将结束评估运行,因为否则它将无法理解堆栈的其余部分(查看堆栈并将其与计算器期望的内容进行比较)你就会明白我的意思)
也像@paulw11一样,我强烈建议在评估开始时设置一个断点,并逐步(非常缓慢地)运行它,因为了解它的工作原理非常有用。
关于ios - return语句在switch中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36660458/