一、通过栈把中缀表达式转换为后缀表达式的步骤:
从左至右扫描中缀表达式,
if(遇到数字){
加入后缀表达式
}else if(遇到 ‘(’ ){
入栈
}else if(遇到 ‘)’ ){
依次将栈中元素出栈并加入到后缀表达式,直到遇到 ‘(’ 并将其从栈中删除
}else if(遇到运算符op){
if(栈顶元是 ‘(’ ){
op入栈
}else{
if(高于栈顶运算符优先级){
op入栈
}else{
依次将比op优先级高的和相等的运算符出栈加入到后缀表达式,
直到遇到比op优先级低的运算符或左括号(低优先级运算符或左括号不出栈)或栈空为止
op入栈
}
}
}
扫描完毕后栈中所有剩下的运算符出栈加入到后缀表达式
二、通过后缀表达式计算表达式的值的步骤:
顺序扫描表达式的每一项
if(遇到操作数){
入栈
}else if(遇到操作符op){
连续从栈中退出两个操作数Y和X(先出栈的为Y)
将 X<op>Y的结果入栈
}
表达式扫描完毕后栈顶元素就是所求的结果
三、计算后缀表达式的代码:
#include <cassert> #include <iostream> #include <string> #include <vector> #include <stack> #include <map> using std::cout; using std::endl; using std::string; using std::vector; using std::stack; using std::map; class CalcExpress { private: enum factorTag{LB,RB,NUM,ADD=10,MINU,MULT = 20,DIV,UNARY=30};//()1 +-*/-//类型标记 //enum设置默认值10,20是为了区分+- */ -(负号),使得相差较大,便于区别 static map<char,enum factorTag> tagPair;//mapTag typedef std::pair<string,enum factorTag> ExpType;//类型,如<'+',ADD> static bool isError;//出错标识 //------------TEST public: static void display(const string & s,const vector<ExpType> & x){ cout<<s<<":"<<endl; for(auto & elem:x){ cout<<elem.first<<"\t\t"<<elem.second<<endl; } cout<<endl; } static void display(const vector<ExpType> & x){ cout<<"----"<<endl; for(auto & elem:x){ cout<<elem.first<<"\t\t"<<elem.second<<endl; } cout<<endl; } static void test(){ string s1("(1+2*-35)/34"); string s2("-1/2-10-(-333+1)"); string s3("-(153+2*3)/4"); string s4("(1+2)*3"); string s5 = "1--2*3/(2/-3-5)"; vector<ExpType> vecTest; //strToExpress(s1,vecTest);display(s1,vecTest); //strToExpress(s2,vecTest);display(s2,vecTest); //strToExpress(s3,vecTest);display(s3,vecTest); vector<ExpType> inExp,postExp; string s = s5; strToExpress(s,inExp); display(s,inExp); inExpToPostExp(inExp,postExp); display(postExp); double ret = calcExpressProcess(postExp); if(!isError){ cout<<"result = "<<ret<<endl; }else{ cout<<"process error"<<endl; } } //------------TEST public: static double calcExpress(const char * str){ if(!str){ isError = true; return 0; } string cppString(str); //判断字符串是否是合法表达式 if(!isValidExpress(cppString)){ isError = true; return 0; } double ret = 0; isError = false; vector<ExpType> express;//数组保存每一个项 strToExpress(cppString,express);//将表达式的每一项存到数组 ret = calcExpressProcess(express); return ret; } private: static bool isValidExpress(const string & cppString){//判断表达式是否合法 //待补充完整 return true; } static void strToExpress(const string & cppString,vector<ExpType> & express){//将string转成ExpType表达式类型 //(1+2*-3)/34 //-1/2-1-(-3+1) //-(1+2*3)/4 express.clear(); size_t preIdx = 0; size_t size = cppString.size(); enum factorTag flag; for(size_t i = 0;i<size;++i){ preIdx = i;//k记录数字的第一个位置 if(cppString[i] == '-'){ if(i==0 || (cppString[i-1] != ')' && !::isdigit(cppString[i-1]))){ //-作为负号的场景:前面不是数字或者) flag = UNARY; }else{//减号 flag = MINU; } }else if(isdigit(cppString[i])){//数字 while(i<size && isdigit(cppString[i])){ ++i; } --i; flag = NUM; }else{ switch(cppString[i]){ case '+': flag = ADD;break; case '*': flag = MULT;break; case '/': flag = DIV;break; case '(': flag = LB;break; case ')': flag = RB;break; default: isError = true; cout<<"express ERROR"<<endl; return; } } express.push_back(ExpType(string(cppString,preIdx,i-preIdx+1),flag)); } } static void inExpToPostExp(const vector<ExpType> & inExp,vector<ExpType> & postExp){ postExp.clear(); postExp.reserve(inExp.size()); stack<ExpType> stk;//栈 for(auto & inTerm:inExp){ if(inTerm.second == NUM){//数值 postExp.push_back(inTerm); }else if(inTerm.second == RB){//右括号 while(!stk.empty()){ if(stk.top().second == LB){//左括号 stk.pop(); break; }else{ postExp.push_back(stk.top()); stk.pop(); } } }else if(inTerm.second == LB){//左括号 stk.push(inTerm); }else{//运算符 while( !stk.empty() && \ (\ (inTerm.second <= stk.top().second) || ((inTerm.second - stk.top().second) == 1) \ )\ ){//如果栈顶是高优先级或平级运算符 postExp.push_back(stk.top()); stk.pop(); } stk.push(inTerm); } } while(!stk.empty()){ postExp.push_back(stk.top()); stk.pop(); } } static double calcExpressProcess(const vector<ExpType> & postExp){ stack<double> calcStk;//栈用于记录中间过程的值 for(auto & postTerm:postExp){ if(postTerm.second == NUM){//数值 calcStk.push(stod(postTerm.first)); }else{//运算符 if(postTerm.second == UNARY){//负号 auto & val = calcStk.top(); val = -val; }else{//其他双目运算符 double num2 = calcStk.top(); calcStk.pop(); double num1 = calcStk.top(); calcStk.pop(); if(postTerm.second == DIV){//判断是否发生除零 const double limit = 0.000000001; if(num2 >= -1*limit && num2 <= limit){//num2为0 isError = true; cout<<"error,Divide zero"<<endl; abort(); } } double val = 0; switch(postTerm.second){ case ADD: val = num1 + num2;break; case MINU: val = num1 - num2;break; case MULT: val = num1 * num2;break; case DIV: val = num1*1.0 / num2;break; default: isError = true; cout<<"express ERROR"<<endl; return 0; } calcStk.push(val); } } } if(calcStk.size() != 1){//最后栈中剩下的数就是结果 isError = true; cout<<"express ERROR"<<endl; return 0; } return calcStk.top(); } }; bool CalcExpress::isError = false; int main(){ CalcExpress::test(); return 0; }