用Objective-C的foundation框架解决表达式求值问题

主要思想:

本程序分2个类

一个是ExpressionString类,主要用于存储表达式以及对它进行求值。以下是该类中的内容:

(NSString *)expString//用于存储要计算的表达式;

-(NSString*)caculateExpression//就用于计算该表达式的值。

另外一个类是ExpressionEvaluation,此类用于辅助ExpressionString类来对表达式进行求值。以下是该类中的内容:

-(id) init; //初始化函数
-(BOOL) isDigital; //判断是否是数字
-(NSString*) precede:(NSString*) a; //判断当前操作符和栈顶操作符的优先级
-(double) compute: (NSString*) opnt anOtherStr: (NSString*) a; //出栈计算

在main函数中,只需要3步就行了。定义、发送赋值消息、输出结果。3个步骤如下:

ExpressionString *es = [ExpressionString alloc];

[es setExpString:@"10÷6×7+15-8"];

//[es setExpString:@"10÷÷6×7+15-8"];   此步骤是用于检查错误的测试用例,当使用这步时,系统会输出错误提示信息。

//[es setExpString:@"1000÷2"];  此步骤用于检测整除之后输出整型,而不是浮点型的值。

NSLog(@"%@",[es caculateExpression]);

具体代码如下:共5个文件。

 1 //
 2 //  ExpressionString.h
 3 //  exp1_2
 4 //
 5 //  Created by junz on 12/27/14.
 6 //  Copyright (c) 2014 Caspar. All rights reserved.
 7 //
 8
 9 #import <Foundation/Foundation.h>
10
11 @interface ExpressionString : NSObject
12 @property NSString *expString;
13 - (NSString*)caculateExpression;
14 @end
  1 //
  2 //  ExpressionString.m
  3 //  exp1_2
  4 //
  5 //  Created by junz on 12/27/14.
  6 //  Copyright (c) 2014 Caspar. All rights reserved.
  7 //
  8
  9 #import "ExpressionString.h"
 10 #import "ExpressionEvaluation.h"
 11 @implementation ExpressionString
 12 @synthesize expString;
 13 - (NSString*)caculateExpression
 14 {
 15     NSMutableArray *array = [[NSMutableArray alloc] init];
 16     for (int i = 0; i < [self.expString length]; i++)//初始化构造数组array存放所有字符
 17     {
 18         NSMutableString *s = [[NSMutableString alloc] init];
 19         s = [NSMutableString stringWithString: [self.expString substringWithRange:NSMakeRange(i, 1)]];
 20         if ([s isEqualToString:@"÷"]) s = [NSMutableString stringWithString: @"/"];
 21         else if ([s isEqualToString:@"×"]) s = [NSMutableString stringWithString: @"*"];
 22         else ;
 23         array[i] = s;
 24     }
 25     array[[array count]] = @"#";//在array数组的末尾加上#作判断符用
 26     //初始化2个栈,OPTR存放操作符,OPND存放操作数
 27     NSMutableArray *OPTR = [[NSMutableArray alloc] init];
 28     NSMutableArray *OPND = [[NSMutableArray alloc] init];
 29     ExpressionEvaluation *current = [ExpressionEvaluation alloc]; //设置一个遍历指针current,从0开始对表达式进行遍历
 30     ExpressionEvaluation *next = [ExpressionEvaluation alloc];
 31     double sum = 0;   //表达式中操作数的值
 32     int i = 0, k = -1, j = -1;//i用来遍历表达式,k用来记录OPND的大小,j用来记录OPTR的大小
 33     int breakflag = 1;
 34     current.str = array[i];
 35     while (![current.str isEqualToString: @"#"])//表达式未遍历完,则不断循环遍历
 36     {
 37         while ([current isDigital]) //判断当前指针所指的字符是不是数字,如果是,则将数字存入OPND
 38         {
 39             sum = 10 * sum + ([[current str] intValue]);
 40             if (i >= ([array count] -  1))
 41             {
 42                 break;
 43             }
 44             [current setStr: array[++i]];
 45             if (![current isDigital]) {
 46                 OPND[++k] = [NSString stringWithFormat:@"%f", sum];
 47                 sum = 0;
 48             }
 49         }
 50         NSInteger flag = 1; //当current指针指向操作符时,则需要与OPTR栈顶元素进行比较
 51         double temp = 0;
 52         if (i < ([array count] -  1)) {//判断表达式的正确性
 53             [next setStr: array[i+1]];
 54             if (![next isDigital] && ((![current.str isEqualToString:@")"] && ![next.str isEqualToString:@"("]) || [current.str isEqualToString:@")"] && [next.str isEqualToString:@"("]) { //情况1:")(";情况2:"**"或者"//"等等
 55
 56                 breakflag = 0;
 57                 break;
 58             }
 59         }
 60         //如果OPTR栈为空,则将当前current所指的操作符进栈
 61         if ((j == -1) && ![current.str isEqualToString:@"#"])
 62         {
 63             OPTR[++j] = [current str];
 64             [current setStr: array[++i]];
 65             flag = 0;
 66         }
 67         //如果当前OPTR不为空,则将current所指的操作符与OPTR栈顶元素进行比较
 68         while (flag && (j >= 0)) {
 69             ExpressionEvaluation *aa = [ExpressionEvaluation alloc];
 70             ExpressionEvaluation *bb = [ExpressionEvaluation alloc];
 71             if ([current.str isEqualToString:@"#"] && (j == -1)) {
 72                 break;
 73             }
 74             switch ([[current precede:OPTR[j]] isEqualToString:@"<"])
 75             {
 76                 case true: //如果OPTR栈顶元素小于current所指的操作符,则current所指的操作符进栈
 77                     OPTR[++j] = [current str];
 78                     [current setStr: array[++i]];
 79                     flag = 0;
 80                     break;
 81                 case false:
 82                     switch ([[current precede:OPTR[j]] isEqualToString:@"="])
 83                 {
 84                     case true: //如果OPTR栈顶元素等于current所指的操作符,则消去括号,并使current指向下一个字符
 85                         j = j - 1;
 86                         [current setStr: array[++i]];
 87                         break;
 88                     case false:
 89                         switch ([[current precede:OPTR[j]] isEqualToString:@">"])
 90                     {   case true://如果OPTR栈顶元素大于current所指的操作符,出栈计算,将结果入OPND栈
 91                             aa.str = OPND[k--];
 92                             bb.str = OPND[k--];
 93                             temp = [bb compute: OPTR[j--] anOtherStr:aa.str];
 94                             OPND[++k] = [NSString stringWithFormat:@"%f", temp];
 95                             break;
 96                         case false: breakflag = 0;break; //判断优先权为0时候的情况
 97                     }
 98                 }
 99                 default: break;
100             }
101             if ((j == -1) && ![current.str isEqualTo:@"#"])//判断OPTR栈是否为空,为空则将current所指的操作符入栈
102             {
103                 OPTR[++j] = [current str];
104                 [current setStr: array[++i]];
105                 flag = 0;
106             }
107         }
108     }
109     if (breakflag) {
110         //以下代码主要是为了防止类似10/2=5.000000的问题,程序从后往前逐个删除0,使最终得到10/2=5。
111         NSMutableString *ss = [NSMutableString stringWithString:OPND[0]];
112         while ([[ss substringWithRange:NSMakeRange(ss.length-1, 1)] isEqualToString:@"0"]) {
113             [ss deleteCharactersInRange:NSMakeRange(ss.length-1, 1)];
114         }
115         if ([[ss substringWithRange:NSMakeRange(ss.length-1, 1)] isEqualToString:@"."]) [ss deleteCharactersInRange:NSMakeRange(ss.length-1, 1)];
116         return ss;
117     }
118     else return @"This is not a correct expression, can not evaluate";
119 }
120 @end
 1 //
 2 //  ExpressionEvaluation.h
 3 //  exp1_2
 4 //
 5 //  Created by junz on 12/27/14.
 6 //  Copyright (c) 2014 Caspar. All rights reserved.
 7 //
 8
 9 #import <Foundation/Foundation.h>
10
11 @interface ExpressionEvaluation : NSObject
12 @property NSMutableString* str;
13
14 -(id) init;
15 -(BOOL) isDigital;  //判断是否是数字
16 -(NSString*) precede:(NSString*) a;  //判断当前操作符和栈顶操作符的优先级
17 -(double) compute: (NSString*) opnt anOtherStr: (NSString*) a;  //出栈计算
18 @end
 1 //
 2 //  ExpressionEvaluation.m
 3 //  exp1_2
 4 //
 5 //  Created by junz on 12/27/14.
 6 //  Copyright (c) 2014 Caspar. All rights reserved.
 7 //
 8
 9 #import "ExpressionEvaluation.h"
10
11 @implementation ExpressionEvaluation
12 @synthesize str;
13
14 -(id) init
15 {
16     self.str = [[NSMutableString alloc] init];
17     return self;
18 }
19 -(BOOL) isDigital
20 {
21     if (([self.str isGreaterThanOrEqualTo:@"0"]) && ([self.str isLessThanOrEqualTo:@"9"])) {
22         return YES;
23     }
24     else return NO;
25 }
26 -(NSString*) precede:(NSString*) a
27 {
28     NSInteger i = 0, j = 0;
29     NSArray *priori = [[NSArray alloc] initWithObjects:
30                        [NSArray arrayWithObjects:@">",@">",@"<",@"<",@"<",@">",@">", nil],
31                        [NSArray arrayWithObjects:@">",@">",@"<",@"<",@"<",@">",@">", nil],
32                        [NSArray arrayWithObjects:@">",@">",@">",@">",@"<",@">",@">", nil],
33                        [NSArray arrayWithObjects:@">",@">",@">",@">",@"<",@">",@">", nil],
34                        [NSArray arrayWithObjects:@"<",@"<",@"<",@"<",@"<",@"=",@"0", nil],
35                        [NSArray arrayWithObjects:@">",@">",@">",@">",@"=",@"0",@">", nil],
36                        [NSArray arrayWithObjects:@"<",@"<",@"<",@"<",@"<",@"0",@"=", nil],
37                        nil];
38     if ([a isEqualToString:@"+"])  i = 0;
39     else if ([a isEqualToString:@"-"])  i = 1;
40     else if ([a isEqualToString:@"*"])  i = 2;
41     else if ([a isEqualToString:@"/"])  i = 3;
42     else if ([a isEqualToString:@"("])  i = 4;
43     else if ([a isEqualToString:@")"])  i = 5;
44     else if ([a isEqualToString:@"#"])  i = 6;
45     else ;
46
47     if ([self.str isEqualToString:@"+"])  j = 0;
48     else if ([self.str isEqualToString:@"-"])  j = 1;
49     else if ([self.str isEqualToString:@"*"])  j = 2;
50     else if ([self.str isEqualToString:@"/"])  j = 3;
51     else if ([self.str isEqualToString:@"("])  j = 4;
52     else if ([self.str isEqualToString:@")"])  j = 5;
53     else if ([self.str isEqualToString:@"#"])  j = 6;
54     else ;
55
56     return  priori[i][j];
57 }
58 -(double) compute: (NSString*)opnt anOtherStr: (NSString*)a
59 {
60     double sum = 0;
61     if ([opnt isEqualToString:@"+"])  sum = [self.str doubleValue] + [a doubleValue];
62     else if ([opnt isEqualToString:@"-"])  sum = [self.str doubleValue] - [a doubleValue];
63     else if ([opnt isEqualToString:@"*"])  sum = [self.str doubleValue] * [a doubleValue];
64     else if ([opnt isEqualToString:@"/"])  sum = [self.str doubleValue] / [a doubleValue];
65     else ;
66     return sum;
67 }
68 @end
 1 //
 2 //  main.m
 3 //  exp1_2
 4 //
 5 //  Created by junz on 12/27/14.
 6 //  Copyright (c) 2014 Caspar. All rights reserved.
 7 //
 8
 9 #import "ExpressionString.h"
10 #import "ExpressionEvaluation.h"
11
12 int main(int argc, const char * argv[]) {
13     @autoreleasepool {
14         ExpressionString *es = [ExpressionString alloc];
15 //        [es setExpString:@"1000÷2"];
16 //        [es setExpString:@"10÷6×7+15-8"];
17 //        [es setExpString:@"10÷÷6×7+15-8"];  //属于错误情况2
18         [es setExpString:@"10÷(6+2)(7)+15-8"]; //属于错误情况1
19         NSLog(@"%@",[es caculateExpression]);
20     }
21     return 0;
22 }

总结:此程序能求解正确表达式的值,但是容错性稍微差了些,比如在main函数中,发这样一条消息:[es setExpString:@"10÷(6+2)(+15-8"];程序直接奔溃,没有实现很好的容错。

解决方法:

需要针对ExpressionString类中的compute方法进行改进。

1、对OPND和OPTR数组取数据时,把取出来的数据在OPND和OPTR中删除;

2、在返回值时,通过判断OPND和OPTR的大小来进行,而不是直接返回OPND[0]。

由于时间问题,此改进的操作等有时间的时候再搞。现在先暂且放一放。

时间: 2024-08-04 01:21:20

用Objective-C的foundation框架解决表达式求值问题的相关文章

java实现算术表达式求值

需要根据配置的表达式(例如:5+12*(3+5)/7.0)计算出相应的结果,因此使用java中的栈利用后缀表达式的方式实现该工具类. 后缀表达式就是将操作符放在操作数的后面展示的方式,例如:3+2 后缀表达式为32+,3*(2+1)的后缀表达式为:321+*,解决表达式求值首先需要根据字符串表达式求出后缀表达式,然后使用后缀表达式和操作数栈实现计算,计算的大致思想是从后缀表达式中取元素,如果元素是数值则加入到操作数栈中,如果是运算符则从操作数栈中取两个数来参与运算.后缀表达式的获取要借助于两个栈

刁肥宅详解中缀表达式求值问题:C++实现顺序/链栈解决

1. 表达式的种类 如何将表达式翻译成能够正确求值的指令序列,是语言处理程序要解决的基本问题,作为栈的应用事例,下面介绍表达式的求值过程. 任何一个表达式都是由操作数(亦称运算对象).操作符(亦称运算符)和分界符组成的.通常,算术表达式有3种表示: ①中缀(infix)表示:<操作数><操作符><操作数>,如A+B. ②前缀(prefix)表示: <操作符><操作数><操作数>,如+AB. ③后缀(postfix)表示: <操作

lintcode 中等题:Evaluate Reverse Polish notation逆波兰表达式求值

题目 逆波兰表达式求值 在逆波兰表达法中,其有效的运算符号包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰计数表达. 样例 ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9 ["4", "13", "5", "/", "+"]

表达式求值_栈

问题 C: 表达式求值 时间限制: 3 Sec  内存限制: 128 MB提交: 1  解决: 1[提交][状态][讨论版] 题目描述 ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧.比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数) 输入 第一行输入一个整数n,共有n组测试数据(n<10).每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每

栈的典型应用-表达式求值【转】

本文转载自:http://www.voidcn.com/blog/lub0807/article/p-1510616.html 栈的一个应用是求四则运算表达式的值,这里的表达式包含数字.加减乘除4种运算符,以及小括号. 由于输入是一个字符串,因此解决这个问题需要以下3个步骤: 1.输入字符串转化为中缀表达式: 2.中缀表达式转化为后缀表达式: 3.后缀表达式求值. 现在表达式为:9 + ( 3 - 1 )* 3 + 10 / 2 ,先看一下运行结果: 首先解释一下中缀表达式和后缀表达式的概念.所

表达式求值:从“加减”到“带括号的加减乘除”的实践过程

本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee ● 为什么想做一个表达式求值的程序 最近有一个需求,策划想设置游戏关卡的某些数值,这个数值不是一个常量,而是根据关卡的某些环境数据套上一个计算表达式算出来的.这个需求无法用excel拖表预计算出,因为关卡的环境数据只有在游戏中才能产生,在excel制表时,这些都是未知的.作为程序员,我可以把计算表达式硬编码在代码中,但这个做法有缺陷,如果策划要修改计算表达式的话,只能通过我修改程序并

将中缀表达式转换为后缀表达式,然后利用栈对表达式求值。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js.js"></script> </head> <body> 输入中缀表达式空格分隔 例如 2 + 3 <input type=

中缀表达式求值总结

中缀表达式的题目困扰了我两三年,都没去写过..这两天看到2005年提高组的T3要用到所以心血来潮写了一下. 表达式求值借助基本结构应该不用说了是栈,不管手写还是STL都没有太大关系.而中缀表达式最难控制的地方是优先级,算上+-*/^()一共有四个优先级[+-,*/,, ^()](后面会提到一个三级的字符“负号”,这是预留空位). 下面对一个例子进行分析:2*3+4*6/3+17-4^2 那么处理的时候怎么控制优先级呢? 搜到‘+’之前,栈的情况是这样的: 操作数栈:2  3 操作符栈:* 然后搜

表达式求值的实现

表达式求值是一个很有意思的技术话题,国内外讨论这个话题的技术人员很多,也有非常多的实现方案.倒不是说这个问题很难解决,只是说它提供了很好的话题,让各路高手使用自己的手段来解决问题,百家争鸣,各展所长.该话题也提供了一个非常好的想像空间让大家一起讨论技术讨论方案,也是一个数据结构教程中的经典教育案例. 一般可以使用堆栈,表达式树(.Net)之类的方法解决,但如果要实现比较复杂的表达式求值,如数据方法求值,字符串,是否求值,方法计算等等,那就不是教学案例了,应该是一个编译器的问题了.即是编写一个编译