码迷,mamicode.com
首页 > 其他好文 > 详细

[Stanford] RPN Calculator(model improved version)

时间:2014-10-04 11:40:46      阅读:206      评论:0      收藏:0      [点我收藏+]

标签: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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!