標籤: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)