当前位置:文档之家› 算术表达式求值

算术表达式求值

题目:算术表达式求值问题内容:一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。

假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。

引入表达式起始、结束符是为了方便。

编程利用“算符优先法”求算术表达式的值。

要求:(1)从键盘读入一个合法的算术表达式,输出正确的结果。

(2)显示输入序列和栈的变化过程。

选作内容:操作数类型扩充到实数。

一:问题分析和任务定义1.问题分析:分析题目并参考书目可以基本了解完成一个算术表达式所存在的问题。

对一个表达式来说,由于各种运算符和界限符的运用,运算符和界限符的优先级决定了算术表达式不是简单的从左往右的运算。

因此设计算法完成算术表达式时就要考虑各运算符和界限符的优先级,同时还要注意操作数与算符的判断。

在算法中要求完成操作数、运算符和界限符的出入栈,运算符和界限符的优先级比较和操作数之间的运算。

最后完成的算法要求输入一个算术表达式,能够正确的计算出来它的最后结果并输出。

为了不用考虑算符优先级,将输入的中缀表达式转换成后缀表达式。

这样就可以知道实现本程序需要进行的操作:1)建立空栈,存储信息;2)运用函数实现出入栈和取栈顶元素操作。

3)将中缀表达式转换成后缀表达式。

4)实现后缀表达式的求解。

5)建立一个函数使中缀表达式能够被有效输入。

本程序的关键是中缀表达式转换成后缀表达式对于栈的操作(1)建空栈setStack() 运算的结果是将栈顶元素返回。

(2)清空栈EmptyStack(),可以用于判断栈内元素的有无,在栈顶元素的输出被使用。

(3)入栈push(),出栈pop()和取栈顶元素top()。

2.任务定义1).本演示程序中,利用栈将输入的中缀表达式转换成后缀表达式,并完成其求解过程来达到计算表达式的目的。

2).演示程序以用户和计算机的对话方式执行,即在计算机终端上显示"提示信息"之后,由用户在键盘上输入演示程序中需要输入的数据,以“回车符”为结束标志。

相应的输入数据和运算结果显示在其后。

3).程序执行的命令包括:1)输入任意一个整数表达式;2)是否继续。

4).测试数据输入一个整数表达式:3+(5*8-9)输出:后缀表达式:3 5 8 *9 -+结果为:34继续?(y/n)二、数据结构的选择和概要设计算术表达式中各数据元素间存在一种线性关系,设计的数据类型如下:#define MAXNUM 50typedef int DataType;typedef struct {DataType s[MAXNUM];int t;}SeqStack,*PSeqStack;//定义一个类型名为SeqStack的数据类型本算法设计过程中只采用加减乘除等四种运算符,题目要求借助栈完成算法设计,提示中要把中缀表达式转换成后缀表达式计算,因此操作运算包括要建空栈、清空栈、进栈、出栈、取栈顶元素,中缀表达式转换成后缀表达式,后缀表达式的运算等。

将运算符和界限符一起描述为算符,本程序的设计如下:(1)先定义一下数据结构来存储算术表达式。

(2)建空栈setstack(),清空栈。

(3)对栈进行的运算函数,出入栈和取栈顶元素。

(4)中缀表达式转换成后缀表达式的函数its()。

(5)后缀表达式计算函数。

(6)设计存放后缀表达式的队列。

(7)主函数main(),使得整个程序完整进行。

三、详细设计和编码为了实现概要设计中的所有数据类型,对每个操作给出算法。

对主程序和其他模块也都需要写出算法。

1)数据类型#define MAXNUM 50typedef int DataType;typedef struct {DataType s[MAXNUM];int t;}SeqStack,*PSeqStack;//定义一个类型名为SeqStack的数据类型建空栈和其它关于栈的操作这部分为栈的运算问题。

为后面表达式转换和计算做准备。

这方面的知识书上有系统讲到,不需要过多去设计算法。

2)表达式的转换和计算将中缀表达式转换成后缀表达式,顺序扫描中缀算术表达式,当读到数字时直接将起送至输出队列中;当读到运算符时,将栈中所有优先级高于或等于该运算符的运算符弹出,送至输出队列中,再将当前运算符入栈;当读入左括号时,即入栈;当读入右括号时,将靠近栈的第一个左括号上面的运算符依次弹出,送至输出队列中,再删除栈中左括号。

在计算后缀表达式式,最后保存的值是最先取出参与运算,所以要用到栈。

读到数字时直接送至输出队列中:switch(c1) {case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':set =1;suffix[j++]=c1; /*遇到数字输出*/break;当读到左括号时入栈:case '(':set=0;push(ps, c1); /*遇到左括号,入栈*/break;当读入右括号时,将靠近栈的第一个左括号上面的运算符依次弹出,送至输出队列中,再删除栈中左括号:case ')':c2 = ')'; /*遇到右括号把右括号赋值给c2*/while(!EmptyStack(ps)) { /*当栈不为空时*/c2=top(ps); /*遇到右括号取栈顶*/pop(ps); /*出栈*/if(c2 =='(')break; /*遇到左括号时停止出栈*/suffix[j++]=c2; /*c2的值放入后缀表达式中*/}当读到加减乘除号时,栈和后缀表达式的变化。

因为优先级的关系,将加减号同时考虑,乘除号同时考虑。

读到加减号处理时运用算法如下:case '+':case '-':while(!EmptyStack(ps)) { /*当栈不为空时*/c2 = top(ps); /*将栈顶元素赋值给c2*/if(c2 =='+'|| c2 =='-'|| c2 == '*' || c2 == '/') {pop(ps); /*遇到加减号时栈中栈顶元素是加减乘除四种运算符出栈*/suffix[j++] = c2; /*将c2放入后缀表达式中*/}else if(c2=='(')break; /*遇到加减号时栈顶元素是左括号不进行出栈*/}push(ps, c1); /*c1入栈*/break;读到乘除号处理时算法与加减法基本一致,但在if语句时只需考虑c2 == '*' || c2 == '/'。

计算后缀表达式时读到数值时计算sum的值switch(c) {case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':if(set == 1) /*遇到操作数*/sum = sum * 10 + c - '0'; /*sum的计算*/else /*所遇到的不是操作数*/sum = c - '0';/*sum的计算*/set=1;break;考虑遇到空格、制符表和运算符时sum值的入栈情况case ' ':case'\t':case '\n':if (set == 1) {push(ps, sum); /*遇到空格或制表符sum入栈*/set = 0; }break;case '+':case '-':case '*':case '/':if(set == 1) {push(ps, sum); /*遇到运算符时sum入栈*/set = 0; }遇到加减乘除四个运算符时将栈顶和次栈顶元素分别运用所遇到运算符进行运算,并将运算结果入栈num2 = top(ps); /*栈顶元素赋值给num2*/pop(ps); /*元素出栈*/if(EmptyStack(ps)) { /*当栈为空*/free(ps); /*释放栈内空间*/return 0;}num1 = top(ps); /*栈顶元素赋值给num1*/pop(ps); /*元素出栈*/if(c == '+') { /*c为加号时*/push(ps, num1 + num2); /*num1与num2的和入栈*/}if(c == '-') { /*c为减号时*/push(ps, num1 - num2); /*num1与num2的差入栈*/}if(c == '*'){ /*c为乘号时*/push(ps, num1 * num2); /*num1与num2的积入栈*/}if(c == '/'){ /*c为除号时*/push(ps, num1 / num2); /*num1与num2的商入栈*/}break;default:free(ps);return 0; }}}该部分为程序的核心算法,即将算术表达式的值正确的输出。

4)主函数基本的数据定义,并实现表达式的输入,并调用getline()函数void main() {char c, infix[MAXNUM], suffix[MAXNUM];int result;int flag = 1;while(flag == 1) {printf("请输入任意一个整数算术表达式:\n");getline(infix, MAXNUM); /*调用getline()函数*/if(its(infix, suffix) == 1) {printf("所得后缀为:%s\n", suffix);}else {printf("无效缀!\n");}调用calculateSuffix()函数使程序完整if(calculateSuffix(suffix, &result) == 1){ /*调用calculateSuffix()函数*/ printf("结果为:%d\n", result);}else {printf("非法后缀!\n");}四、上机调试1.编程中遇到的几个问题刚看到题目的时候,我对题意没有理解,运用的普通的方法来完成程序,运行时输入无括号的算术表达式可以正确输出结果,但输入带括号的表达式时输出的结果与运算结果不符。

相关主题