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]。

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

  • 相关阅读:
    第一周软件测试
    第八周
    第七
    安卓第六周作业
    安卓第五周
    第四周作业
    Jsp第十次作业
    Jsp第九次作业(带验证码的email)
    Jsp第八次作业
    Jsp第七次作业email
  • 原文地址:https://www.cnblogs.com/casparzheng/p/4192879.html
Copyright © 2011-2022 走看看