首页 > 代码库 > [Stanford] RPN Calculator(model improved version)
[Stanford] RPN Calculator(model improved version)
以前的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)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。