用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的机试,压轴便为此题,今天抽空对其进行了研究. 算术表达式中最常见的表示法形式有 中缀.前缀和 后缀表示法.中缀表示 ...
随机推荐
- POJ 3080 Blue Jeans (KMP)
求出公共子序列 要求最长 字典序最小 枚举第一串的所有子串 然后对每一个串做KMP.找到目标子串 学会了 strncpy函数的使用 我已可入灵魂 #include <iostre ...
- ubuntu下设置开机自启动项
可用一些小工具来管理 Ubuntu 的启动选项: 小工具 rcconf: #sudo apt-get rcconf #sudo apt-get install rcconf root 下运行: #su ...
- java nio 抛出NonWritableChannelException异常
抛出异常的代码在此处: MappedByteBuffer buffer = channel.map(MapMode.READ_WRITE, 0, avalible); 其中channel是一个file ...
- android学习日记09--BitMap操作
Bitmap android里的图像处理重要的类,支持jpg.png.bmp等格式的图像,BitmapDrawable是封装Bitmap的一个对象,Bitmap实现在android.graphics包 ...
- pomelo组件..
1.pomelo会加载lib/components目录下的组件.并设置为属性..和存储在Pomelo.components中..注意这里其实存储的是对象的构造函数.. function load() ...
- android128 zhihuibeijing 科大讯飞 语音识别
- 科大讯飞 开放平台 http://open.voicecloud.cn/ package com.itheima.voicedemo; import android.app.Activity; i ...
- Java基础知识强化之网络编程笔记15:Android网络通信之 Android异步任务处理(AsyncTask使用)
AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的 ...
- Android_Spinner_Listener
xml布局文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xml ...
- rust haskell
http://www.rust-lang.org <null>
- jquery用on代替bind(),live(),delegate()的方法
Js的功能确实非常强大,奈何我一个php程序员一直在js上没有投入足够的精力去研究,每次遇到不会的都是去百度,以后有时间真的应该买本书系统的学习一下 // Bind $( "#members ...