c++棧實現簡單計算器
阿新 • • 發佈:2018-12-30
/* 棧實現計算器,主要思路就是設定一個符號棧和一個數字棧,在字串首尾各加一個'#',然後掃描字串, * 如果是數字進數字棧,如果是運算子號先判斷符號優先順序,若棧外符號優先順序大於棧內符號優先順序則進棧, * 小於棧內優先順序則符號棧出棧一位,數字棧出棧兩位進行計算,結果重新存進數字棧,直到棧外優先順序大於棧內, */ #include <iostream> #include <string> #include <algorithm> #include <cmath> using namespace std; const int MAX = 30; const int DONE = 1; /* run this program using the console pauser or add your own getch, system("pause") or input loop */ //棧定義 template <class T> class Stack{ public: Stack(int MaxStackSize=10); ~Stack() { delete [] stack;} bool IsEmpty() const {return top==-1;} bool IsFull() const {return top==MaxTop;} T Top() const; Stack<T>& Add(const T& x); Stack<T>& Del(T& x); void MakeEmpty(){top=-1;} //清空棧 void print(){ for(int i; i < top + 1; i ++){ cout<<stack[i]<<'\t'; } cout<<endl; } private: int top;//棧頂 int MaxTop;//最大的棧頂值 T *stack;//堆疊元素陣列 }; template<class T> Stack<T>::Stack(int MaxStackSize){ MaxTop=MaxStackSize-1; stack=new T[MaxStackSize]; top=-1; } template<class T> Stack<T>& Stack<T>::Add(const T& x){ if(IsFull()) {cout<<"no memory;"<<endl;return *this;} top=top+1; stack[top]=x; return *this; } template<class T> Stack<T>& Stack<T>::Del(T& x){ if(IsEmpty()) {cout<<"no element"<<endl;return *this;} x=stack[top]; top=top-1; return *this; } template<class T> T Stack<T>::Top() const{ return stack[top]; } //判斷一個字元是否為數字 bool isNum(char c){ if((c > '0'||c == '0')&&(c < '9'||c == '9')) return true; else return false; } //刪除字串中的空格 void deleteBlank(string &s){ string::iterator i = s.begin(); while ((i=find(i, s.end(), ' '))!=s.end()) s.erase(i); } //計算器 class Calculator{ public: Calculator(string s); ~Calculator(); int outPriority(char); //返回棧外優先順序 int inPriority(char); //返回棧內優先順序 bool judgePri(char, char); //判斷優先順序 前一個為棧外符號,後一個為棧內符號 若前大於後返回1,否則返回0 int judgePri(char); //判斷運算子 若是'#'返回 -1,若是')'返回 0,否則返回 1 void dealNum(); //處理資料 int calculate(); //計算 void setString(string const s){ this->s = '#' + s + '#'; deleteBlank(this->s); //刪除字串中的空格 } private: Stack<char> *s_sym; //符號棧 Stack<int> *s_num; //資料棧 string s; }; Calculator::Calculator(string s){ this->s = '#' + s + '#'; deleteBlank(this->s); s_sym = new Stack<char>(MAX); s_num = new Stack<int>(MAX); } Calculator::~Calculator(){ delete s_sym; delete s_num; } int Calculator::outPriority(char symble){ switch(symble){ case '#': return 0; case '(': return 8; case '+': return 2; case '-': return 2; case '*': return 4; case '/': return 4; case '%': return 4; case '^': return 6; case ')': return 1; default: throw 1; } } int Calculator::inPriority(char symble){ switch(symble){ case '#': return 0; case '(': return 1; case '+': return 3; case '-': return 3; case '*': return 5; case '/': return 5; case '%': return 5; case '^': return 7; case ')': return 8; default: throw 1; } } bool Calculator::judgePri(char out, char in){ if(outPriority(out) > inPriority(in)) return true; else return false; } int Calculator::judgePri(char symble){ if(symble == '#') return -1; else if(symble == ')') return 0; else return 1; } void Calculator::dealNum(){ //將資料棧中的前兩個彈出進行計算,結果放回資料棧,符號棧彈出頂部元素 char _temp = 0; int dtemp1 = 0; int dtemp2 = 0; s_sym->Del(_temp); s_num->Del(dtemp1); s_num->Del(dtemp2); switch(_temp){ case '+': dtemp2 += dtemp1; break; case '-': dtemp2 = dtemp2 - dtemp1; break; case '*': dtemp2 = dtemp2 * dtemp1; break; case '/': if(dtemp1 == 0) throw 0; else dtemp2 = dtemp2 / dtemp1; break; case '%': dtemp2 = dtemp2 % dtemp1; break; case '^': dtemp2 = pow(dtemp2,dtemp1); break; default: throw 1; } s_num->Add(dtemp2); } int Calculator::calculate(){ for(int i = 0; i < s.size(); i ++){ //遍歷字串 if(isNum(s[i])){ int temp = (int)(s[i]) - 48; //char強制型別轉換為int ascii 碼數值,減 48 轉換為對應整數值 int _temp = 0; if(i > 0 && isNum(s[i - 1])){ s_num->Del(_temp); temp = _temp * 10 + temp; } s_num->Add(temp); }else{ char temp = s[i]; if(s_sym->IsEmpty()){ s_sym->Add(temp); }else{ if(judgePri(temp, s_sym->Top())){ s_sym->Add(temp); }else if(judgePri(temp) == 1){ //棧外優先順序小於棧內優先順序,且不為 '#' 和 ')' while(!judgePri(temp, s_sym->Top())){ //當棧外優先順序比棧內優先順序低時,執行棧內符號運算 dealNum(); } s_sym->Add(temp); }else if (judgePri(temp) == -1){ while(s_sym->Top() != '#'){ dealNum(); } int result = s_num->Top(); s_sym->MakeEmpty(); s_num->MakeEmpty(); return result; } else if(judgePri(temp) == 0){ while(s_sym->Top() != '('){ dealNum(); } s_sym->Del(temp); } } } } } int main(int argc, char** argv) { try{ string s = ""; Calculator c(s); while(DONE){ s = ""; cout<<"請輸入一個表示式"<<endl; getline(cin, s); c.setString(s); int result = 0; result = c.calculate(); cout<<c.calculate()<<endl; system("pause"); system("cls"); } } catch(int i){ if(i == 0) cout<<"除數不能為0!"; else if(i == 1) cout<<"存在無法識別的符號!"<<endl; } return 0; }