您的位置:首页 > 理论基础 > 数据结构算法

利用栈求表达式的值(数据结构课程设计)

2017-06-27 11:22 295 查看
课程设计的内容和要求(包括原始数据、技术要求、工作要求等)编写程序实现表达式求值,即验证某算术表达式的正确性,若正确,则计算该算术表达式的值。主要功能描述如下:1、从键盘上输入表达式。2、分析该表达式是否合法:(1)是数字,则判断该数字的合法性。若合法,则压入数据到堆栈中。(2)是规定的运算符,则根据规则进行处理。在处理过程中,将计算该表达式的值。(3)若是其它字符,则返回错误信息。

运算符优先级

对于连个相继出现的操作符θ1和θ2 有三种关系:大于、等于和小于。由此可以列出“+-*/”之间的优先级。如下表:
 +-*/()#
+>><<<>>
->><<<>>
*>>>><>>
/>>>><>>
(<<<<<= 
)>>>> >>
#<<<<< =
 加减乘除优先性都低于“(”但是高于“)”,由运算从左到右可知,当θ1=θ2 ,令θ1>θ2为了算法简洁,在表达式的左边和右边虚设一个“#”,这一对“#”表示一个表达式求值完成。“(”=“)”当一对括号相遇时表示括号内已运算完成。“)”和“(”、“#”和“(”、“(”和“#”无法相继出现如果出现则表达式出现语法错误。为实现优先算法,可以使用两个工作栈,一个是OPTR,用于寄存运算符,一个是OPND,用于寄存运算数和运算结果。

算法基本思路。

首先置操作数栈为空栈,表达式起始符为“#”为栈底元素。依次读入表达式中的每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权作相应操作,直至整个表达式求值完毕(OPTR栈顶元素和当前读入的字符均为“#”)
#include<stdio.h>
#include<cstdio>
#include<math.h>
#include<stdlib.h>
#include<stack>
using namespace std;
stack<double>opnd;  //存储运算数
stack<char>optr;  //存储运算符
char pre; //记录当前字符的前一个字符,用于负数的判断
int flag ; //值=1表示为负数,否则为正数

void init(){  //初始化
optr.push('#');
pre = '#';
flag = 0;
}

int IsNumber(char c){  //检查是否是数字
if(c >= '0' && c <= '9')return 1;
return 0;
}

int ErrorCheck(char c){  //返回1表示不是规定运算符
if(c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#')return 0;
return 1;
}

char Precede(char f,char l){   //运算级判断
if(f == '+' || f == '-'){
if(l == '*' || l == '/' || l == '(') return '<';
else return '>';
}
if(f == '*' || f == '/'){
if(l == '(') return '<';
else return '>';
}
if(f == '('){
if(l == ')') return '=';
else if(l!='#')return '<';
}
if(f ==')' && l !='(') return '>';
if(f == '#'){
if(l == '#') return '=';
else if(l!=')')return '<';
}

return '0';
}

double Compute(double b,char oper,double a){
if(oper == '-') return a-b;
if(oper == '+') return a+b;
if(oper == '*') return a*b;
if(oper == '/') return a/b;
}

int main(){
init();
char ch = getchar();
while(ch != '#' || optr.top() != '#'){
if(IsNumber(ch)){
double tot = 0;
do{
tot *= 10;
tot += (ch - '0');
pre = ch;
ch = getchar();
}while(IsNumber(ch));

if(ch == '.'){  //小数点后的数值
ch = getchar();
double tmp = 0.1;
while(IsNumber(ch)){
tot += (ch - '0')*tmp;
tmp *= 0.1;
pre = ch;
ch = getchar();
}
}
if(flag){
tot = 0 - tot;
flag = 0;
}
opnd.push(tot);
}else if(ch == '-' && (pre == '#' || pre == '(')){   //负数的判定
flag = 1;
ch = getchar();
}else {
if(ErrorCheck(ch)) {
printf("存在非规定的运算字符!\n");
return 0;
}

switch(Precede(optr.top(),ch)){
case '<' :{     //栈顶运算符优先级小
optr.push(ch);
pre = ch;
ch = getchar();  //重新接收下一个字符
break;
}
case '=' :{
optr.pop(); //出栈一对括号
pre = ch;
ch = getchar(); //重新接收下一个字符
break;
}
case '>' :{
char oper = optr.top();
optr.pop();  //出栈一个运算符
double a = opnd.top(); opnd.pop();
double b = opnd.top(); opnd.pop();  //出栈两个操作数

double tot = Compute(a,oper,b);  //计算值,并将结果压入堆栈
opnd.push(tot);
break;
}
case '0':{
printf("表达式语法错误,括号不匹配!\n");
return 0;
break;
}
} //switch
}  //else
} //while

printf("%.2lf\n",opnd.top());
opnd.pop();
return 0;
}
输入形式如:2+(-2+10)*5/2#    以#号结尾
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: