计算一个表达式的运算结果
使用C++自带stack堆栈对象来实现
参考课本的伪代码,把伪代码改造成可运行的代码
课本伪代码请下载本附件:表达式伪c代码
例如
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();


第一个输入t,表示有t个实例
第二行起,每行输入一个表达式,每个表达式末尾带#表示结束
输入t行
每行输出一个表达式的计算结果,计算结果用浮点数(含4位小数)的格式表示
用cout控制浮点数输出的小数位数,需要增加一个库文件,并使用fixed和setprecision函数,代码如下:
#include <iostream>
#include<iomanip>
using namespace std;
int main()
{ double temp = 12.34
cout<<fixed<<setprecision(4)<<temp<<endl;
}
输出结果为12.3400
#include<iostream>
#include<stack>
#include<string>
#include<sstream>
#include<iomanip>
using namespace std;
#define ok 0
#define error -1
#define opsetsize 7//运算符集合长度,目前只有7个运算符
char Prior[7][7]=
{
///运算符间的优先关系,分别是+ - * / ( ) #
///按行看+ - * / ( ) #
‘>‘,‘>‘,‘<‘,‘<‘,‘<‘,‘>‘,‘>‘,
‘>‘,‘>‘,‘<‘,‘<‘,‘<‘,‘>‘,‘>‘,
‘>‘,‘>‘,‘>‘,‘>‘,‘<‘,‘>‘,‘>‘,
‘>‘,‘>‘,‘>‘,‘>‘,‘<‘,‘>‘,‘>‘,
‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘=‘,‘ ‘,
‘>‘,‘>‘,‘>‘,‘>‘,‘ ‘,‘>‘,‘>‘,
‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘ ‘,‘ ‘
};
double Operate(double a,char theta,double b)
{
if(theta==‘+‘)
return a+b;
else if(theta==‘-‘)
return a-b;
else if(theta==‘*‘)
return a*b;
else if(theta==‘/‘)
return a/b;
return error;
}
char opset[opsetsize]={‘+‘, ‘-‘, ‘*‘, ‘/‘, ‘(‘, ‘)‘,‘#‘};///运算符集合
int in(char Test,char *p)///1是运算符,0不是运算符
{
///判断字符Test是否是运算符
for(int j=0;j<opsetsize;j++)
{
if(Test==p[j])
return 1;
}
return 0;
}
char precede(char Aop,char Bop)
{
///获取两个运算符之间的优先级,Aop是栈顶,Bop是下一个运算符
int i;
for(i=0;i<opsetsize;i++)
if(opset[i]==Aop)
break;
int j;
for(j=0;j<opsetsize;j++)
if(opset[j]== Bop)
break;
return Prior[i][j];
}
double EvaluateExpression(string Myexp)
{
stack<char>Optr;///运算符栈
stack<double>Opnd;///操作数栈
string Tempdata;
double data;
char theta;
char c;
int i=0;///用于控制字符串的位置移动
stringstream ss;
Optr.push(‘#‘);///先压入一个#号
c= Myexp[0];
while(c!=‘#‘||Optr.top()!=‘#‘)
{
if(in(c, opset)==0)
{
///判断读入的字符是不是操作数,是则进入
Tempdata+=c;
c=Myexp[++i];///读取下一个字符
if(in(c, opset)!=0)
{
///如果c是运算符,表明前面读入了一个完整的操作数
ss.clear();
if(Tempdata.size()!=0)
{
ss<<Tempdata;
ss>>data;
Opnd.push(data);
Tempdata.clear();
}
}
}
else
{
///是运算符,开始计算
switch(precede(Optr.top(),c))
{
case‘<‘:///栈顶的优先级低,即Op1<Op2,不进行计算,压入新的运算符
Optr.push(c);
c= Myexp[++i];
break;
case‘=‘:///脱括号和脱#号
Optr.pop();
c=Myexp[++i];
break;
case‘>‘:///退栈并将计算结果入栈
double b=Opnd.top();///第一个弹出右操作数
Opnd.pop();
double a=Opnd.top();///第二个弹出左操作数
Opnd.pop();
theta=Optr.top();
Optr.pop();
Opnd.push(Operate(a,theta,b));
break;
}
}
}
return Opnd.top();
}
int main()
{
string exp;
int T;
cin>>T;
while(T--)
{
cin>>exp;
exp+="#";
double result=EvaluateExpression(exp);
cout<<fixed<<setprecision(4)<<result<<endl;
}
return 0;
}