用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个文件。
//
// ExpressionString.h
// exp1_2
//
// Created by junz on 12/27/14.
// Copyright (c) 2014 Caspar. All rights reserved.
// #import <Foundation/Foundation.h> @interface ExpressionString : NSObject
@property NSString *expString;
- (NSString*)caculateExpression;
@end
//
// ExpressionString.m
// exp1_2
//
// Created by junz on 12/27/14.
// Copyright (c) 2014 Caspar. All rights reserved.
// #import "ExpressionString.h"
#import "ExpressionEvaluation.h"
@implementation ExpressionString
@synthesize expString;
- (NSString*)caculateExpression
{
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = ; i < [self.expString length]; i++)//初始化构造数组array存放所有字符
{
NSMutableString *s = [[NSMutableString alloc] init];
s = [NSMutableString stringWithString: [self.expString substringWithRange:NSMakeRange(i, )]];
if ([s isEqualToString:@"÷"]) s = [NSMutableString stringWithString: @"/"];
else if ([s isEqualToString:@"×"]) s = [NSMutableString stringWithString: @"*"];
else ;
array[i] = s;
}
array[[array count]] = @"#";//在array数组的末尾加上#作判断符用
//初始化2个栈,OPTR存放操作符,OPND存放操作数
NSMutableArray *OPTR = [[NSMutableArray alloc] init];
NSMutableArray *OPND = [[NSMutableArray alloc] init];
ExpressionEvaluation *current = [ExpressionEvaluation alloc]; //设置一个遍历指针current,从0开始对表达式进行遍历
ExpressionEvaluation *next = [ExpressionEvaluation alloc];
double sum = ; //表达式中操作数的值
int i = , k = -, j = -;//i用来遍历表达式,k用来记录OPND的大小,j用来记录OPTR的大小
int breakflag = ;
current.str = array[i];
while (![current.str isEqualToString: @"#"])//表达式未遍历完,则不断循环遍历
{
while ([current isDigital]) //判断当前指针所指的字符是不是数字,如果是,则将数字存入OPND
{
sum = * sum + ([[current str] intValue]);
if (i >= ([array count] - ))
{
break;
}
[current setStr: array[++i]];
if (![current isDigital]) {
OPND[++k] = [NSString stringWithFormat:@"%f", sum];
sum = ;
}
}
NSInteger flag = ; //当current指针指向操作符时,则需要与OPTR栈顶元素进行比较
double temp = ;
if (i < ([array count] - )) {//判断表达式的正确性
[next setStr: array[i+]];
if (![next isDigital] && ((![current.str isEqualToString:@")"] && ![next.str isEqualToString:@"("]) || [current.str isEqualToString:@")"] && [next.str isEqualToString:@"("]) { //情况1:")(";情况2:"**"或者"//"等等 breakflag = ;
break;
}
}
//如果OPTR栈为空,则将当前current所指的操作符进栈
if ((j == -) && ![current.str isEqualToString:@"#"])
{
OPTR[++j] = [current str];
[current setStr: array[++i]];
flag = ;
}
//如果当前OPTR不为空,则将current所指的操作符与OPTR栈顶元素进行比较
while (flag && (j >= )) {
ExpressionEvaluation *aa = [ExpressionEvaluation alloc];
ExpressionEvaluation *bb = [ExpressionEvaluation alloc];
if ([current.str isEqualToString:@"#"] && (j == -)) {
break;
}
switch ([[current precede:OPTR[j]] isEqualToString:@"<"])
{
case true: //如果OPTR栈顶元素小于current所指的操作符,则current所指的操作符进栈
OPTR[++j] = [current str];
[current setStr: array[++i]];
flag = ;
break;
case false:
switch ([[current precede:OPTR[j]] isEqualToString:@"="])
{
case true: //如果OPTR栈顶元素等于current所指的操作符,则消去括号,并使current指向下一个字符
j = j - ;
[current setStr: array[++i]];
break;
case false:
switch ([[current precede:OPTR[j]] isEqualToString:@">"])
{ case true://如果OPTR栈顶元素大于current所指的操作符,出栈计算,将结果入OPND栈
aa.str = OPND[k--];
bb.str = OPND[k--];
temp = [bb compute: OPTR[j--] anOtherStr:aa.str];
OPND[++k] = [NSString stringWithFormat:@"%f", temp];
break;
case false: breakflag = ;break; //判断优先权为0时候的情况
}
}
default: break;
}
if ((j == -) && ![current.str isEqualTo:@"#"])//判断OPTR栈是否为空,为空则将current所指的操作符入栈
{
OPTR[++j] = [current str];
[current setStr: array[++i]];
flag = ;
}
}
}
if (breakflag) {
//以下代码主要是为了防止类似10/2=5.000000的问题,程序从后往前逐个删除0,使最终得到10/2=5。
NSMutableString *ss = [NSMutableString stringWithString:OPND[]];
while ([[ss substringWithRange:NSMakeRange(ss.length-, )] isEqualToString:@""]) {
[ss deleteCharactersInRange:NSMakeRange(ss.length-, )];
}
if ([[ss substringWithRange:NSMakeRange(ss.length-, )] isEqualToString:@"."]) [ss deleteCharactersInRange:NSMakeRange(ss.length-, )];
return ss;
}
else return @"This is not a correct expression, can not evaluate";
}
@end
//
// ExpressionEvaluation.h
// exp1_2
//
// Created by junz on 12/27/14.
// Copyright (c) 2014 Caspar. All rights reserved.
// #import <Foundation/Foundation.h> @interface ExpressionEvaluation : NSObject
@property NSMutableString* str; -(id) init;
-(BOOL) isDigital; //判断是否是数字
-(NSString*) precede:(NSString*) a; //判断当前操作符和栈顶操作符的优先级
-(double) compute: (NSString*) opnt anOtherStr: (NSString*) a; //出栈计算
@end
//
// ExpressionEvaluation.m
// exp1_2
//
// Created by junz on 12/27/14.
// Copyright (c) 2014 Caspar. All rights reserved.
// #import "ExpressionEvaluation.h" @implementation ExpressionEvaluation
@synthesize str; -(id) init
{
self.str = [[NSMutableString alloc] init];
return self;
}
-(BOOL) isDigital
{
if (([self.str isGreaterThanOrEqualTo:@""]) && ([self.str isLessThanOrEqualTo:@""])) {
return YES;
}
else return NO;
}
-(NSString*) precede:(NSString*) a
{
NSInteger i = , j = ;
NSArray *priori = [[NSArray alloc] initWithObjects:
[NSArray arrayWithObjects:@">",@">",@"<",@"<",@"<",@">",@">", nil],
[NSArray arrayWithObjects:@">",@">",@"<",@"<",@"<",@">",@">", nil],
[NSArray arrayWithObjects:@">",@">",@">",@">",@"<",@">",@">", nil],
[NSArray arrayWithObjects:@">",@">",@">",@">",@"<",@">",@">", nil],
[NSArray arrayWithObjects:@"<",@"<",@"<",@"<",@"<",@"=",@"", nil],
[NSArray arrayWithObjects:@">",@">",@">",@">",@"=",@"",@">", nil],
[NSArray arrayWithObjects:@"<",@"<",@"<",@"<",@"<",@"",@"=", nil],
nil];
if ([a isEqualToString:@"+"]) i = ;
else if ([a isEqualToString:@"-"]) i = ;
else if ([a isEqualToString:@"*"]) i = ;
else if ([a isEqualToString:@"/"]) i = ;
else if ([a isEqualToString:@"("]) i = ;
else if ([a isEqualToString:@")"]) i = ;
else if ([a isEqualToString:@"#"]) i = ;
else ; if ([self.str isEqualToString:@"+"]) j = ;
else if ([self.str isEqualToString:@"-"]) j = ;
else if ([self.str isEqualToString:@"*"]) j = ;
else if ([self.str isEqualToString:@"/"]) j = ;
else if ([self.str isEqualToString:@"("]) j = ;
else if ([self.str isEqualToString:@")"]) j = ;
else if ([self.str isEqualToString:@"#"]) j = ;
else ; return priori[i][j];
}
-(double) compute: (NSString*)opnt anOtherStr: (NSString*)a
{
double sum = ;
if ([opnt isEqualToString:@"+"]) sum = [self.str doubleValue] + [a doubleValue];
else if ([opnt isEqualToString:@"-"]) sum = [self.str doubleValue] - [a doubleValue];
else if ([opnt isEqualToString:@"*"]) sum = [self.str doubleValue] * [a doubleValue];
else if ([opnt isEqualToString:@"/"]) sum = [self.str doubleValue] / [a doubleValue];
else ;
return sum;
}
@end
//
// main.m
// exp1_2
//
// Created by junz on 12/27/14.
// Copyright (c) 2014 Caspar. All rights reserved.
// #import "ExpressionString.h"
#import "ExpressionEvaluation.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
ExpressionString *es = [ExpressionString alloc];
// [es setExpString:@"1000÷2"];
// [es setExpString:@"10÷6×7+15-8"];
// [es setExpString:@"10÷÷6×7+15-8"]; //属于错误情况2
[es setExpString:@"10÷(6+2)(7)+15-8"]; //属于错误情况1
NSLog(@"%@",[es caculateExpression]);
}
return ;
}
总结:此程序能求解正确表达式的值,但是容错性稍微差了些,比如在main函数中,发这样一条消息:[es setExpString:@"10÷(6+2)(+15-8"];程序直接奔溃,没有实现很好的容错。
解决方法:
需要针对ExpressionString类中的compute方法进行改进。
1、对OPND和OPTR数组取数据时,把取出来的数据在OPND和OPTR中删除;
2、在返回值时,通过判断OPND和OPTR的大小来进行,而不是直接返回OPND[0]。
由于时间问题,此改进的操作等有时间的时候再搞。现在先暂且放一放。
用Objective-C的foundation框架解决表达式求值问题的更多相关文章
- java实现算术表达式求值
需要根据配置的表达式(例如:5+12*(3+5)/7.0)计算出相应的结果,因此使用java中的栈利用后缀表达式的方式实现该工具类. 后缀表达式就是将操作符放在操作数的后面展示的方式,例如:3+2 后 ...
- 刁肥宅详解中缀表达式求值问题:C++实现顺序/链栈解决
1. 表达式的种类 如何将表达式翻译成能够正确求值的指令序列,是语言处理程序要解决的基本问题,作为栈的应用事例,下面介绍表达式的求值过程. 任何一个表达式都是由操作数(亦称运算对象).操作符(亦称运算 ...
- Aviator 表达式求值引擎开源框架
简介¶ Aviator是一个高性能.轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值.现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢? Aviato ...
- 【算法】E.W.Dijkstra算术表达式求值
算术表达式求值 我们要学习的一个栈的用例同时也是展示泛型的应用的一个经典例子,就是用来计算算术表达式的值,例如 ( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) ) 如果将4乘以5,把3 ...
- lintcode 中等题:Evaluate Reverse Polish notation逆波兰表达式求值
题目 逆波兰表达式求值 在逆波兰表达法中,其有效的运算符号包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰计数表达. 样例 ["2", "1&q ...
- nyist0j 35 表达式求值
题目链接:表达式求值 该题以前做过但是WA了,今天终于把他解决了,各种悲剧啊,又是考虑不周到啊................... 所以贴出来纪念一下,并作为一个警示 /**** ps:注意当遇到 ...
- 函数嵌套 lisp表达式求值
问题 D: lisp表达式求值 时间限制: 1 Sec 内存限制: 128 MB提交: 105 解决: 43[提交][状态][讨论版] 题目描述 lisp是一种非常古老的计算机语言,是由约翰·麦卡 ...
- 第四届河南省ACM 表达式求值 栈
表达式求值 时间限制: 1 Sec 内存限制: 128 MB 提交: 14 解决: 7 [提交][状态][讨论版] 题目描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简 ...
- C++之字符串表达式求值
关于字符串表达式求值,应该是程序猿们机试或者面试时候常见问题之一,昨天参加国内某IT的机试,压轴便为此题,今天抽空对其进行了研究. 算术表达式中最常见的表示法形式有 中缀.前缀和 后缀表示法.中缀表示 ...
随机推荐
- webViewDidFinishLoad因为网页里的重定向,会调用多次,使用web view.isLoading来解决
我编码如下,但我发现 webViewDidFinishLoad() 会发生若干次. 如何知道 webViewDidFinishLoad() 最后发生吗? iNavigate = ; - (void)w ...
- 基于华为Java编程规范的Eclipse checkStyle.xml
发现项目组成员代码规范存在较大的问题,于是就在华为编程规范的基础上制定了这份checkStyle.xml文档,至于Eclipse怎么安装checkStyle插件以及该插件怎么使用请自行Google之. ...
- valgrind 生成mysqld调用图之 select now()跟踪
1.mysqld起动方式: 1.mysqld以root用户运行 valgrind --tool=callgrind --separate-threads=yes --trace-children=y ...
- PAT 1015
1015. Reversible Primes (20) A reversible prime in any number system is a prime whose "reverse& ...
- Apache中 RewriteRule 规则参数介绍
Apache中 RewriteRule 规则参数介绍 摘要: Apache模块 mod_rewrite 提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求.它支持每个完整规则可以拥有不限数量 ...
- 根据字符串计算UILabel尺寸
iOS开发中经常会遇到UILabel大小尺寸不固定的情况,需要根据文字内容变化,这时候就需要计算文字大小以自动改变UILabel的尺寸. iOS7之后计算尺寸只需要一个方法就可以: - (CGSize ...
- 深入理解Binder(二),Binder是什么?
上篇文章深入理解Binder(一),从AIDL谈起我们介绍了AIDL的基本使用,用AIDL两个App的通信是实现了,可是又有小伙伴疑惑了,为什么使用AIDL就能够实现两个App之间的通信?本文我们就来 ...
- 利用动画+div的前后切换实现轮播
可以利用两块div(分别设为前和后),用绝对定位使两块div重合,再利用z-index实现两块div的堆叠顺序(即显示的变换),利用动画和定时器实现轮播,这就是基本的思路. 完整的顺序如下: 1.先设 ...
- 谈谈项目中遇到的各种iOS7适配问题
由于我的项目要适配到iOS7.1, 而现在已经是9时代了,在实际工作中我也是遇到了各种奇葩的坑,所以我想尽快把遇到的iOS7适配问题和解决方案分享出来,以后这些东西可能就用处不大了. 1.字体问题 i ...
- web项目设计与开发——DBHelper3
本次学习的内容为根据DBHelper对数据库里的数据进行增删改查 具体内容为: 一.编写程序 1.创建工程——Mangage 2.在src目录下创建五个包,分别为DAO,DBHelper,Ent ...