标签:style blog color io os ar for strong 数据
以前的model是把操作数压入栈里,遇到加减乘除号直接计算结果,改进版的是把操作数和加减乘除号都压入栈里,controller里的接口不变:
CalculatorBrain.h
#import <UIKit/UIKit.h> @interface CalculatorBrain : NSObject -(void)pushOperand:(double)operand; -(double)performOperation:(NSString *)operation; @property(readonly)id program; +(double)runProgram:(id)program; @end
CalculatorBrain.m
#import "CalculatorBrain.h" @interface CalculatorBrain() @property(nonatomic,strong)NSMutableArray *programStack; //原来的operandStack只能保存运算数, //这个programStack可以同时保存运算数和运算符号。 @end @implementation CalculatorBrain @synthesize programStack=_programStack; -(NSMutableArray *)programStack //需要getter方法做延迟初始化 { if(_programStack==nil) _programStack=[[NSMutableArray alloc] init]; return _programStack; } -(void)pushOperand:(double)operand //操作数入栈 { [self.programStack addObject:[NSNumber numberWithDouble:operand]]; } -(double)performOperation:(NSString *)operation //执行运算只需要将运算符入栈再运行计算程序,最后再返回一个值 { [self.programStack addObject:operation] //添加运算符到栈上,这样栈上就有了操作数和运算符。 return [CalculatorBrain runProgram:self.program] //这里的返回值是计算结果,所以需要运行计算程序runProgram } -(id)program //getter方法 { return [self.programStack copy]; //copy做了2件事,一是它生成了一个副本,所以不再是把原本的内部数据交出去, //二是,对可变数组的copy会返回不可变数组吗?不能修改的。现在你调用之后得到program,即使你用了内省,你也没办法对它做什么。 } +(double)popOperandOffStack:(NSMutableArray *)stack //递归调用,这里的参数不再是id的,而是NSMutableArray,编译器会把关 { double result=0; id topOfStack=[stack lastObject]; //如果stack是nil,则会返回nil if (topOfStack) [stack removeLastObject]; //如果topOfStack是nil,则本句不会被执行 if ([topOfStack isKindOfClass:[NSNumber class]]) { result=[topOfStack doubleValue]; } else if([topOfStack isKindOfClass:[NSString class]]) { NSString *operation=topOfStack; if ([operation isEqualToString:@"+"]) { result=[self popOperandOffStack:stack]+[self popOperandOffStack:stack]; } else if([@"*" isEqualToString:operation]) { result=[self popOperandOffStack:stack]*[self popOperandOffStack:stack]; } else if([@"-" isEqualToString:operation]) { result=[self popOperandOffStack:stack]-[self popOperandOffStack:stack]; } else if([@"/" isEqualToString:operation]) { result=[self popOperandOffStack:stack]/[self popOperandOffStack:stack]; } } return result; } +(double)runProgram:(id)program //改,使得不但可以入栈操作符数和运算符,还能入栈变量.比如x、y等 { NSMutableArray *stack; //建一个本地变量 if ([program isKindOfClass:[NSArray class]]) //用内省判断program是否是数组,然后再赋值给stack { stack=[program mutableCopy]; //本地变量stack,用内省对它做了2件事:一是确保了它是数组,二是做了可变的复制,so可吃掉它了 } //因为runProgram实现的方法是用递归把栈上的东西都消化掉,需要它可变才能消化掉。(递归就是循环直到最后的条件成立,最后条件就是一个空数组或者得到一个结果。)stack是静态类型,而mutableCopy返回id。id和静态类型的相互赋值是可以的。编译器不会警告,要自己知道。 return[self popOperandOffStack:stack]; //因为runProgram是类方法,所以popOperandOffStack也是一个类方法,self是class。 //主要就是对计算的结果进行出栈。如果栈顶是数字就返回数字,如果是个运算符,就对其求值。 } //如果传进来的不是数字和字符串“+”“-”“*”“/”,那么也不会崩溃。因为popOperandOffStack中的if和else if都不满足,就执行return result,也就是0.所以我们不怕传进来垃圾数组,这很重要。
[Stanford] RPN Calculator(model improved version)
标签:style blog color io os ar for strong 数据
原文地址:http://www.cnblogs.com/Xylophone/p/4005707.html