1. 程式人生 > >中綴表示式轉換成字尾表示式,進行簡單表示式的計算

中綴表示式轉換成字尾表示式,進行簡單表示式的計算

分析:

  1. 步驟一:中綴表示式轉換為字尾表示式
  • 設立一個操作符棧,用來臨時存放操作符;設定一個佇列用以存放字尾表示式序列。
  • 從左至右遍歷中綴表示式,如果遇到運算元(需要注意的是運算元可能不止一位,因此需要一位位的讀入然後合併成整數)就將其加入到字尾序列中。
  • 如果遇到操作符,如果是左括號‘(’就直接壓入棧中,如果是右括號‘)’就依次彈出棧中元素直至左括號出現。否則將其與棧頂元素比較優先順序大小。如果該操作符的優先順序更大,那麼直接壓入棧中。否則每次將棧頂元素彈出,依次加入佇列,直至操作符優先順序大於了新的棧頂元素的優先順序。
  • 重複上述步驟直至遍歷完中綴表示式,如果最後棧中還有元素,那麼就依次彈出,加入到佇列中,直至棧空
  1. 步驟二:計算字尾表示式

從左至右掃描字尾表示式,如果是運算元,那麼壓入棧中,如果是操作符那麼就從棧中彈出兩個運算元(注意,這兩運算元和操作符的結合順序是固定的,先彈出的是第二運算元結合到操作符的右邊,後彈出的是第一運算元結合到操作符的左邊)結合操作符進行運算。並將得到的新的運算元壓入到棧中。反覆以上步驟直到掃描完字尾表示式。那麼最後剩下的就是最終的接過了。

注意:本程式關於括號的處理那一塊有問題。我現在還很菜沒有找到問題在哪,待以後再改。

#include<iostream>
#include<stack>
#include<queue>
#include<string> #include<map> #include<fstream> using namespace std; struct node{ //定義結構體,該結構體用於儲存每次處理的字元 char op; //如果是操作符,存入到op中,並且要將flag置為false double data; //如果是運算元,存入到data中,並且要將flag置為true bool flag; }; stack<node> s; //操作符棧,存放操作符的臨時工作棧。
queue<node> q; //字尾表示式佇列 map<char,int> op; //操作符優先順序 void change(string str){ op['+']=op['-']=1; //輸入操作符優先順序 op['*']=op['/']=2; for(int i=0;i<str.length();){ node temp; if(str[i]>='0'&&str[i]<='9'){ //如果是運算元的話 temp.flag =true; //標記置為true temp.data=str[i++]-'0'; //儲存到臨時結構體temp中 while(i<str.length() && str[i]>='0' && str[i]<='9'){ //因為數字可能不止一位,因此迴圈至不是數字為止 temp.data=temp.data*10+(str[i]-'0'); //組成整數 i++; } q.push(temp); //將該運算元扔進字尾序列的佇列中 } else if(str[i]=='('){ //之前一直以為我這一塊處理括號的寫錯了。。。。。後來發現程式碼沒錯。。。是因為自己輸入的是中文括號。。。 temp.flag =false; temp.op =str[i]; //是左括號直接壓入佇列 s.push(temp); i++; } else if(str[i]==')'){ //終於等到了右括號 while(s.top().op!='('){ //將棧裡面的操作符彈出到字尾表示式中,知道碰到了左括號 q.push(s.top()); s.pop(); } s.pop() ; //扔掉左括號 i++; } else{ temp.flag =false; //如果是操作符,那麼標記置為false while(!s.empty()&&op[str[i]]<=op[s.top().op]){ //只有當該操作符的優先順序高於棧頂元素的優先順序,才壓入棧內 q.push(s.top()); //否則將棧頂元素彈出,壓入到佇列中 s.pop() ; } temp.op=str[i]; s.push(temp); i++; } } while(!s.empty()){ //最後如果操作符棧還不空的話。依次彈出壓入到佇列中 q.push(s.top()); s.pop() ; } } double cal(){ //計算字尾表示式 node cur,temp; double temp1,temp2; //第一運算元,第二運算元 while(!q.empty()){ cur=q.front(); //取得隊首元素 q.pop() ; if(cur.flag==true){ //如果是運算元,壓入棧中 s.push(cur); } else{ //如果是操作符 temp2=s.top().data ; //取出第二運算元 s.pop() ; temp1=s.top().data ; //取出第一運算元 s.pop() ; temp.flag =true; //臨時存放結果的temp,當然是新的運算元 if(cur.op =='+'){ temp.data =temp1+temp2; } else if(cur.op =='-'){ temp.data =temp1-temp2; } else if(cur.op =='*'){ temp.data =temp1*temp2; } else{ temp.data =temp1/temp2; } s.push(temp); } } return s.top().data; //最後棧頂剩的唯一一個元素就是最終的結果了 } int main() { string str; //fstream fin("C://Users/haha/Desktop/input.txt",ios::in); //筆者當時從檔案中讀取的表示式 cin>>str; change(str); //改成字尾表示式 cout<<cal(); //計算結果。 }