主要思想:
本程序分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]。
由于时间问题,此改进的操作等有时间的时候再搞。现在先暂且放一放。