zoukankan      html  css  js  c++  java
  • 用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]。

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

  • 相关阅读:
    el-select下拉框选项太多导致卡顿,使用下拉框分页来解决
    vue+elementui前端添加数字千位分割
    Failed to check/redeclare auto-delete queue(s)
    周末啦,做几道面试题放松放松吧!
    idea快捷键
    解决flink运行过程中报错Could not allocate enough slots within timeout of 300000 ms to run the job. Please make sure that the cluster has enough resources.
    用.net平台实现websocket server
    MQTT实战3
    Oracle 查看当前用户下库里所有的表、存储过程、触发器、视图
    idea从svn拉取项目不识别svn
  • 原文地址:https://www.cnblogs.com/casparzheng/p/4192879.html
Copyright © 2011-2022 走看看