#include <iostream>
#include <stack>
#include <cmath>
using namespace std;
class calc{
char* expression;
enum token{OPAREN ,ADD ,SUB ,MULTI, DIV, EXP, CPAREN, VALUE, EOL};//已经按照优先级排列了:whyEOL:类比EOF(文档的结束),这里是表达式的结束
void BinaryOp(token op,stack<int>&dataStack);//要是对栈操作要&
token getOp(int &value);
public:
calc(char *s){
expression=new char[strlen(s)];
strcpy(expression,s);//这两个顺序别反了
}
~calc(){
delete expression;
}
int result();
};
//控制计算先后
int calc::result(){
token lastOp,topOp;
int resultValue=0,currentValue=0;
stack<int>dataStack;
stack<token>opStack;//注意这个类型
char *str=expression;//提前保留expression的第一个位置指针。
while ((lastOp=getOp(currentValue))!=EOL) {//这里一定要加(),C++短路求值,先判断左边的条件,再右边。搞不清楚就分开来写。
switch (lastOp) {
case VALUE:
dataStack.push(currentValue);
break;
case OPAREN:
opStack.push(lastOp);
break;
case CPAREN:
while (!opStack.empty() && (topOp=opStack.top())!=OPAREN) {//不能写‘(’,因为栈里面存储的是token类型。
BinaryOp(topOp, dataStack);
opStack.pop();
}
if (topOp!=OPAREN) {
cerr<<"缺左括号"<<endl;
}
if(opStack.top()==OPAREN)opStack.pop();//把‘(’pop
break;
case MULTI:case DIV: case ADD:case SUB:
while (!opStack.empty() && (topOp=opStack.top())>=lastOp) {
BinaryOp(topOp, dataStack);
opStack.pop();
}//注意是while!!
opStack.push(lastOp);//最后自己肯定要入栈
break;
case EXP:
opStack.push(EXP);
break;
default:
break;
}
}
while (!opStack.empty()) {
BinaryOp(opStack.top(), dataStack);
opStack.pop();
}
//结果处理,三种情况
if (dataStack.empty()) {
cerr<<"无结果"<<endl;
return 0;
}
resultValue=dataStack.top();
dataStack.pop();
if (!dataStack.empty()) {
cerr<<"缺操作符"<<endl;
return 0;
}
expression=str;
return resultValue;
}
//getOp:从表达式取一个合法的符号:运算符/运算数
calc::token calc::getOp(int &value){//注意:返回值token 是在calc中定义的枚举,所以要说明范围,不然找不到
while (*expression&&*expression==' ') {//判断*expression!=NULL防止爆掉,字符串操作要注意这个
expression++;//向后跳过空格
}
value=0;
if(*expression>='0'&&*expression<='9'){
while(*expression>='0'&&*expression<='9'){
value=value*10+*expression-'0';
expression++;
}//数字处理
return VALUE;//why return VALUE??
}
else{
char e=expression[0];
expression++;
switch (e) {
case '(':
return OPAREN;
break;
case ')':
return CPAREN;
break;
case '+':
return ADD;
break;
case '-':
return SUB;
break;
case '*':
return MULTI;
break;
case '/':
return DIV;
break;
case '^':
return EXP;
break;
default:
return EOL;
break;
}
}
}
//BinaryOp:运算符与运算数的结合,也就是发生运算
void calc::BinaryOp(token op,stack<int> &dataStack){
int num1,num2;
if(dataStack.empty())
{cerr<<"缺操作数!"<<endl;exit(1);}
else {num2=dataStack.top();dataStack.pop();}
if(dataStack.empty())
{cerr<<"缺操作数!"<<endl;exit(1);}
else{num1=dataStack.top();dataStack.pop();}
switch (op) {
case ADD:
dataStack.push(num1+num2);
break;
case SUB:
dataStack.push(num1-num2);
break;
case MULTI:
dataStack.push(num1*num2);
break;
case DIV:
dataStack.push(num1/num2);
break;
case EXP:
dataStack.push(pow(num1,num2));
break;
default:
break;
}
}
int main() {
char* s;
cout<<"请输入要计算的表达式:"<<endl;
cin>>s;
calc c(s);
cout<<c.result();
return 0;
}