表达式计算思路:
1)准备两个栈,一个数据栈,一个运算符栈。
反复读取表达式:(2、3、4)
2)如果是数,入数栈。
3)如果是左括号,入运算符栈。如果是右括号,反复从运算符栈顶取运算符合从数据栈中取两个数据进行计算,并把运算结果入数据栈,直到遇到栈顶或左括号为止。
4)如果是运算符,先跟栈顶的运算符比,只要不高于栈顶优先级,就取出栈顶的运算符和数据栈中的两个数据进行计算,把结果入数据栈,直到高于栈顶运算符优先级或者遇到左括号或者运算符栈空为止。
5)处理栈中的运算符:取出栈顶的运算符和数据栈的两个数据进行运算,并把结果入数据栈,直到运算符栈空为止。
6)这时数据栈中的数据就是计数结果。
#include<iostream>
#include<stack>
#include<string>
#include<cstring>
using namespace std;
class Exp
{
stack<char> ops; //运算符栈
stack<double> ds; //数据栈
double v,lh,rh; //结果、左运算符、右运算符
char op; //操作符
public:
double calinput() //读取计数表达式直到结束
{
do
{
readdata(); //读取数据
skipspace(); //跳过空白字符
}while(readop()); //读取运算符
calremain();
return v;
}
void readdata() //读取数据可能遇到'('
{
while(!(cin >> v)) //读取失败因该是‘(’
{
cin.clear();
cin >> op; //读取‘(’
if(op != '(')
{
throw string("在该出现数值得地方遇到了") + op;
}
ops.push(op);
}
ds.push(v);
}
void skipspace()
{
while(cin.peek() == ' ' || cin.peek() == '\t')
{
cin.ignore();
}
}
bool readop() //读取运算符可能遇到‘)’或者‘\n’
{
while((op=cin.get()) == ')')
{
while(ops.top() != '(') //栈中的‘(’
{
rh = ds.top(); ds.pop(); //从栈中取右操作数
lh = ds.top(); ds.pop(); //从栈中取左操作数
ds.push(cal(lh,ops.top(),rh)); //计算结果入栈
ops.pop();
}
ops.pop(); //丢弃栈中的‘(’
}
if(op == '\n') return false;
if(strchr("+-*/",op) == NULL)
{
throw string("无效运算符")+op;
}
while(!ops.empty() && ops.top() != '(' && prior(op,ops.top()))
{
rh = ds.top(); ds.pop(); //从栈中取右操作数
lh = ds.top(); ds.pop(); //从栈中取左操作数
ds.push(cal(lh,ops.top(),rh)); //计算结果入栈
ops.pop();
}
ops.push(op); //预算符入栈
return true;
}
void calremain()
{
while(!ops.empty())
{
rh = ds.top(); ds.pop(); //从栈中取右操作数
lh = ds.top(); ds.pop(); //从栈中取左操作数
ds.push(cal(lh,ops.top(),rh)); //计算结果入栈
ops.pop();
}
if(ds.size()!= 1)
{
throw string("无效表达式");
}
v = ds.top();
ds.pop();
}
double cal(double lh, char op, double rh)
{
return op == '+' ? lh + rh :
op == '-' ? lh - rh :
op == '*' ? lh * rh : lh/rh;
}
bool prior(char op1, char op2) // op1的优先级是否高于op2
{
return op1 != '+' && op1 != '-' && op2 != '*' && op2 != '/';
}
};
int main ()
{
Exp e;
try
{
cout << e.calinput() <<endl;
}
catch(const string& e)
{
cout << e <<endl;
}
}