问题描述
这里限定的简单算术表达式求值问题是,用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式,计算该表达式的运算结果。
设计运算算法
- 中缀表达式
在算术表达式中,运算符位于两个操作数中间的表达式称为中缀表达式。
例:1 + 2 * 3
中缀表达式运算一般遵循“先乘除,后加减,从左至右,先括号内,再括号外”的规则。一次中缀表达式不仅要依赖运算符优先级,还要处理括号。 - 后缀表达式
后缀表达式就是运算符在操作数的后面
例:1 + 2 * 3 的后缀表达式为 1 2 3 * +
对于后缀表达式,它已经考虑了运算符的优先级,没有括号,只有操作数和运算符。其求值过程是,从左到右读入后缀表达式,若读入的是操作数,将它入数值栈,若读入的是一个运算符,从数值栈中连续出栈两个元素(两个操作数),并将结果入数值栈。对整个后缀表达式读入结束后,栈顶元素就是计算结果。
代码实现
1.定义一个Calculator类
#define MAX 100
#include<stack>
#include<cstring>
#include<iostream>
using namespace std;
class Calculator{
public:
void convert();//将中缀表达式转化为后缀表达式
void calculate();//计算后缀表达式
int priority(const char c);//得到运算符优先级
void input();//输入算术表达式
private:
char* exp;//存放中缀表达式
char postExp[MAX];//存放后缀表达式
int len,pnum;
};
2.得到运算符优先级
int Calculator::priority(const char c){
switch(c){
case '+':
case '-':
return 1;
break;
case '*':
case '/':
return 2;
break;
}
}
3.输入算术表达式
void Calculator::input(){
exp = new char[MAX];
cout << "请输入算式:" ;
string str;
cin >> str;
strcpy(exp,str.c_str());
len = str.length(); //len表示中缀表达式长度
}
4.将中缀表达式转换成后缀表达式
void Calculator::convert(){
stack<char> op;
int i=0,j=0;//i,j分别作为exp和postExp的下标
for(i=0;i<len;i++){
if(exp[i]>='0'&&exp[i]<='9')//如果是数字,直接放入postExp
{
postExp[j++] = exp[i];
if(exp[i+1]<'0'||exp[i+1]>'9'){
postExp[j++] = '#';//用‘#’标识有个数值串结束
}
}else if(exp[i]=='+'||exp[i]=='-'||exp[i]=='*'||exp[i]=='/'){
while(true){
if(op.empty()||op.top()=='('){//当栈为空,或栈顶为(
op.push(exp[i]);
break;
}else if(priority(exp[i])>priority(op.top())){//当当前运算符优先级大于栈顶优先级
op.push(exp[i]);
break;
}else{
postExp[j++]=op.top();//小于等于
op.pop();
}
}
}else{
if(exp[i]=='('){//直接压入
op.push(exp[i]);
}else{//当当前运算符为)时
while(op.top()!='('){
postExp[j++] = op.top();
op.pop();
}
op.pop();//把(退栈
}
}
}
while(!op.empty()){//将栈中所有运算符退栈并放入postExp中
postExp[j++] = op.top();
op.pop();
}
pnum = j;//保存在postExp中字符的个数
}
5.计算后缀表达式
void Calculator::calculate(){
stack<double> st;
double a,b,c;
int i=0;
char ch;
while(i<pnum){
ch=postExp[i];
switch(ch){
case '+':
a=st.top();
st.pop();
b=st.top();
st.pop();
st.push(b+a);
break;
case '-':
a=st.top();
st.pop();
b=st.top();
st.pop();
st.push(b-a);
break;
case '*':
a=st.top();
st.pop();
b=st.top();
st.pop();
st.push(b*a);
break;
case '/':
a=st.top();
st.pop();
b=st.top();
st.pop();
if(a!=0){
st.push(b/a);
}else{
cout << "除数不能为0" << endl;
exit(0);
}
break;
default://处理数字字符
c=0;
while(ch>='0'&&ch<='9'){
c = 10*c+(ch-'0');//将连续的字符转换成数值存放到c
i++;
ch=postExp[i];
}
st.push(c);//将数组c进栈
break;
}
i++;
}
cout << "计算结果为:" << st.top();//栈顶元素即为求值结果
}
6.主函数
int main(){
Calculator c;
c.input();
c.convert();
c.calculate();
return 0;
}