我来构思一下,其实计算器算是有点小复杂。先观察一下mac上的计算器程序。它有一个显示窗口,下面是按键。随便输入一些东西,会发现有几个需要注意的地方。A如果连续输入数字会累加成一个数字,但是不是单纯的字符串连接然后转换成数字。比如依顺序按1,2,3键,输入框会先显示1 然后显示12 然后显示123。这个过程中,这个数,都是一个整数。如果你现在再按一下小数点,会发现变成了123. 然后不管你再按多少小数点,都还是123.不变。如果继续按数字键,会继续按float的形式累加。这时你再按小数点键,也不会有反应的。B除了数字,计算器的按键还剩下操作符。通过一些尝试,发现操作符有两种,一种是二元的。比如,你先输入123 屏幕显示123,再按+,屏幕显示123+,此时如果你按其他二元操作符,只会将123+变成其他二元操作符对应的符号,比如你按*,就会变成123*。如果你再继续按数字键输入一串数字,比如456这时会变成456+。在这种情况下按=号,会开始计算并显示结果。 另一种是一元的,比如,√ ̄,当你输入4,再按下√ ̄按钮,结果会直接计算出来,这里是2 值得注意的是,比如前面说到的,先按123,再按+,这时显示123+了,如果你现在按√ ̄会直接计算123的平方根。还有一点,比如你依次按下1,+,1 现在显示1+ 如果你再按一下一个二元操作符,比如*,这时1+1会马上计算,变成结果,再加上你刚出输入的二元操作符现在是2*。另外有点特殊情况,就是如果你先按1,再按+,这时直接按等号,会当成1+1来计算的。C小结,以此可见,计算器在运算的逻辑上,采用一种规则,这种规则可以归纳如下: 1. 表达式由数字和操作符组成 2. 表达式的结果是一个数字,或者是一个非数字(有的特殊运算的特殊条件会出现这种数学上未定义结果) 3. 一元操作符只和一个数字相关,并且会立即计算结果 4. 二元操作符和两个数字相关,不会立即计算结果,会在=操作符被按下时,或者另一个二元操作符被按下时计算,特殊情况,在一个数字和一个二元操作符的情况按下=,相对于,把这个数字分别作为二元操作符的两个操作数来计算。 5. 表达式的结果,会直接保留,显示,并可以开始下一次计算。好了,现在可以大概的开始设计计算器的组成元素了 定义抽象基类,CalcUnit :NSObject计算单元。把数字和操作符都视作计算单元 有抽象方法 NSString* display; //获取显示字符串定义数字, CalcNum : CalcUnit 定义一元操作符CalcUnaryOperator : CalcUnit 定义枚举类型:UnaryType {SQRT, COS, SIN} 等 有私有成员 UnaryType type; 初始化方法 id initWithType:(UnaryType) aType; 方法 CalcNum* calculate:(CalcNum*) input1;//计算结果 定义二元操作符CalcBinaryOperator :CalcUnit定义枚举类型:BinaryType {ADD, MINUS, DIV} 等 有私有成员 BinaryType type; 初始化方法 id initWithType:(BinaryType) aType; 有方法 CalcNum* calculate:(CalcNum*) input1 binary:(CalcNum*) input2 ;//计算结果这两类操作符的用法是,比如按下+号,就初始化一个 CalcUnit* unit = [ [CalcBinaryOperator alloc] initWith:ADD]; 把它压入表达式栈。 然后定义表达式栈Expression ,它的成员由一个长度为3的NSMutableArray 一个代表栈顶位置的整数top组成,它的方法有 void push:(CalcUnit*) unit; //压入计算单元 CalcUnit* pop; //弹出计算单元 void clean; //清栈 (计算器的清栈,其实是清除栈内容后,再压入一个数字0) CalcUnit* peek:(int)position; //观察栈上指定位置的单元 我们的Calculator计算器类,方法很简单,只有 void put:(CalcUnit*) unit; //放置一个计算单元,对应UI一次按键 void start; //开始计算结果, 对应按下=号 NSString* getDisplayContent; //返回显示内容,计算器初始化后马上调用这个,会得到字符串“0”,每次按键后,调用这个,会获得计算后的显示结果。 Calculator管理着表达式栈,比如,你点了1+1,表达式栈里面分别有了这3个单元,点击等号时,你开始计算,这时你遍历表达式栈,发现有2个NUM,一个Operator。符合小结的第4种情况,肯定这是一个二元操作符,这时你把2个NUM按其在栈上的先后顺序传给Operator的 CalcNum* calculate:(CalcNum*) input1 binary:(CalcNum*) input2 ; 结果搞定,清栈,把结果压入栈。比如,你点了2键,再点√ ̄键,这时Calculator发现输入的是一个一元操作符,符合小结的第3种情况,立即计算调用Operator的CalcNum* calculate:(CalcNum*) input1; 结果搞定,清栈,把结果压入栈。比如 在表达式栈为1+1的情况下,你按+键,符合小结第3种情况,直接计算,把结果压栈,再压入+操作符。这些东西归纳的很粗糙,已经可以满足初步的功能,有的细节,你修改一下就可以满足。