题目描述
使用C++自带的stack栈模板来实现四则运算表达式求值
算法描述参考第3.2.5节
算法伪代码参考P53-54的算法3.4
例如
1. Push (OPTR, '#');表示把字符#压入堆栈OPTR中,转换成c++代码就是OPTR.push('#');
2. Pop(OPND, a); 表示弹出栈OPND的栈顶元素,并把栈顶元素放入变量a中。因此改成c++代码是两个操作:a = OPND.top(); OPND.pop();
3. a = GetTop(OPND)表示获取栈OPND的栈顶元素,转成c++代码就是: a = OPND.top();
大家主要是改造表达式求值函数EvaluateExpression的代码
输入
第一个输入t,表示有t个实例
第二行起,每行输入一个表达式,每个表达式末尾带#表示结束
输入t行
输出
每行输出一个表达式的计算结果,计算结果用浮点数(含2位小数)的格式表示
参考代码如下:
#include
#include
using namespace std;
int main()
{ double temp = 12.345678
cout<
}
输出结果为12.35
输入样例:
2
1+2*3-4/5#
(66+(((11+22)*2-33)/3+6)*2)-45.6789#
输出样例
6.20
54.32
思路分析
这道题最重要的就是要把表达式转换成后缀表达式。比如,原表达式是= a * b + (c - d / e) * f就变为a b * c d e / - f * + ,这样运算符出现的顺序就正好是实际运算的顺序。那么怎么样把原表达式变为后缀表达式呢?用两个栈OPTR和OPND来分别运算符和数值,遍历表达式,当遇见数值时,直接入OPND。遇见运算符时,比较该运算符与栈顶运算符的优先级顺序,若该运算符的优先级高,入栈;否则,将OPND的上两个数取出来进行运算,并把运算结果存入OPND栈顶。
当读到#时说明该表达式结束,OPND中的元素就是最终的计算结果。
AC代码
#include
#include
#include
#include
#include
using namespace std;
#define OPSETSIZE 7
unsigned char Prior[7][7] = { //运算符间的优先关系
'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=',' ',
'>','>','>','>',' ','>','>',
'<','<','<','<','<',' ','='
};
char OPSET[OPSETSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'}; //运算符集合
double Operate(double a, unsigned char theta, double b); //计算类似a+b的表达式结果
bool In(char Test, char* TestOp); //判断字符Test是否是运算符,是则返回true
char precede(char Aop, char Bop); //返回两个运算符优先级的比较结果
//以下完成算术表达式求值函数EvaluateExpression(string MyExp)的填空
double EvaluateExpression(string MyExp) //算术表达式求值算法
//设OPTR和OPND分别为运算符栈和运算数栈
//参数MyExp是表达式字符串
{ stack OPTR; //运算符栈,字符元素
stack OPND; //运算数栈,实数元素
char TempData[20];
double Data,a,b, r;
char theta, c,x,Dr[2];
OPTR.push('#');
strcpy(TempData,"\0");
int i=0; //表达式字符串的当前字符位置
c = MyExp[i]; //表达式字符串的当前字符
//逐个读入表达式字符串的字符到变量c,并识别为数值或运算符,做相应处理
while (c!='#'||OPTR.top()!='#') {
// if (c == '#') {
// // return OPND.top();
// break;
// }
// if (OPTR.top() == '#') {
// // return OPND.top();
// break;
// }
if (In(c, Dr)) {
switch (precede(OPTR.top(), c)) {
case '<':
OPTR.push(c);
i++;
c = MyExp[i];
break;
case '=':
OPTR.pop();
i++;
c = MyExp[i];
break;
case '>': {
theta = OPTR.top();
OPTR.pop();
b = OPND.top();
OPND.pop();
a = OPND.top();
OPND.pop();
OPND.push(Operate(a, theta, b));
break;
}
}
} else {
string str;
int k=0;
while (1) {
if (In(MyExp[i], Dr)) {
TempData[k]='\0';
break;
}
else {
TempData[k]=MyExp[i];
i++;
k++;
c=MyExp[i];
}
}
sscanf(TempData, "%lf", &Data);
OPND.push(Data);
}
}
return OPND.top();
} //这是函数EvaluateExpression的右花括号
//函数EvaluateExpression的代码到此结束
//以下填空完成其他函数的定义,包括函数Operate\函数In\函数precede
//可以参考教材光盘中文件夹CHAP03的源代码ALGO0304.cpp,几乎照抄
double Operate(double a, unsigned char theta, double b) {
switch (theta) {
case '+':
return a + b;
break;
case '-':
return a - b;
break;
case '*':
return a * b;
break;
case '/':
return a / b;
break;
default :
break;
}
}
bool In(char Test, char* TestOp) {
for (int i = 0; i < OPSETSIZE; i++) {
if (Test == OPSET[i]) return true;
}
return false;
}
char precede(char Aop, char Bop) {
int a, b;
for (int i = -0; i < OPSETSIZE; i++) {
if (Aop == OPSET[i]) a = i;
if (Bop == OPSET[i]) b = i;
}
return Prior[a][b];
}
//主函数
int main()
{ string Exp;
int t;
double result;
cin>>t;
while (t--)
{ cin>>Exp;
result=EvaluateExpression(Exp);
cout<