今天进行了CS193P第三课的学习,课程的主要目标是通过MVC的模式来完成计算器DEMO.但是DEMO的计算方法是通过模拟入栈出栈以及通过递归的方式来进行.我对栈以及递归还不是很熟悉.所以学习效果很差,只弄懂了前50分中左右的内容.
第一遍照着代码完全的敲了下来,没有遇到swift版本转换的问题.主要还是要细心.
第二遍看还是没能完全明白递归的部分,待学习递归后还是要进行第三遍的学习.
具体代码如下,目前将学到的地方都进行了注释
- Model部分
import Foundation //iOS的核心服务层,永远不要再model里导入UIKit
class CalculatorBrain {
private enum Op { //利用枚举的计算属性
case Operand(Double) //操作数
case UnaryOperation(String, Double -> Double) //一元运算,String表示符号,在这里实际表示"√"
case BinaryOperation(String, (Double, Double) -> Double) //二元运算,这里String是加减乘除
var description:String {
get {
switch self {
case .Operand(let operand):
return "\(operand)"
case .UnaryOperation(let symbol,_ ):
return symbol
case .BinaryOperation(let symbol, _):
return symbol
}
}
}
}
private var opStack = [Op]() //运算栈
private var knownOps = [String:Op]() //创建字典,key是string也就是操作符,Op是value也就是操作数
init() {
func learnOp(op:Op) {
knownOps[op.description] = op
}
learnOp(Op.BinaryOperation("×", *))
learnOp(Op.BinaryOperation("÷", {$1 / $0}))
learnOp(Op.BinaryOperation("+", +))
learnOp(Op.BinaryOperation("−", {$0 - $1}))
learnOp(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)//此处就意味着返回最后一个操作数result和剩下的操作符
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)
}
func evaluate() -> Double? {
let (result, remainder) = evaluate(opStack)
return result
}
func pushOperand(operand: Double) -> Double? { //将操作数入栈
opStack.append(Op.Operand(operand))
return evaluate()
}
func performOperation(symbol: String) -> Double?{ //执行运算
if let operation = knownOps[symbol] {
opStack.append(operation)
}
return evaluate()
}
}
- Controller部分
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var display: UILabel!
var userIsInTheMiddleOfTypingANumber = false //用来判断是否已经输入了数字,初始默认为未输入
var brain = CalculatorBrain() //用来连接Controller和Model
@IBAction func appendDigit(sender: UIButton) {//此处实现了,让所有数字button都集中在这一个方法里
let digit = sender.currentTitle! //此处用来识别是按了哪个数字,digit的类型为String
print("digit = \(digit)")
//此处判断是否正在输入数字
if userIsInTheMiddleOfTypingANumber {
display.text = display.text! + digit
} else {
display.text = digit
userIsInTheMiddleOfTypingANumber = true
}
}
@IBAction func operate(sender: UIButton) { //创建运算符操作方法
if userIsInTheMiddleOfTypingANumber {
enter()
}
if let operation = sender.currentTitle {
if let result = brain.performOperation(operation){
displayValue = result
}else {
displayValue = 0
}
}
}
@IBAction func enter() {
userIsInTheMiddleOfTypingANumber = false
if let result = brain.pushOperand(displayValue) {
displayValue = result
}else {
displayValue = 0
}
}
var displayValue: Double {
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue //将display.text转化为Double类型
}
set {
display.text = "\(newValue)" //此处的newValue为默认名称.因为没有给setter定义新的参数名.若设置则可set(新参数名){}
}
}
}