【應用】浮點數四則運算器 Part2:轉化模組的編寫
根據在 【應用】浮點數四則運算器 Part1:輸入模組的編寫 中的規劃,有如下思路:
需要計算的部分實際上是flag=0的部分,其餘部分都有其他對應的操作。
當flag=0時,
1.掃描all全部資料,找到其中字母元x,檢查是否有對應值。
若沒有:返回error code 3: undefined 'x',x是字母元的名稱。繼續輸入下一組資料
若全部有對應值,將其轉化為其對應值。
這樣就得到了完全又數字和操作符組成的表示式,同時完成了期望3.能夠識別沒有賦初值的字母元。
這裡用到的是map的函式find()。
number.find();
空返回number.end(),不空返回這個值。
2.識別錯誤型別:是否缺少或多餘運算子。
缺少或多餘運算子的特徵有以下幾種:
1)數字的下一個是數字或括號'('。數字的上一個是括號')'。
2)操作符的下一個是操作符或空串。操作符的上一個是空串。
可以將數字編為1,括號'('編為2,括號')'編為3,操作符編為4。
若當前位置編碼為1,當上一個為3時輸出error code 4: operation after ')' needed
若當前位置編碼為1,當下一個為2時輸出error code 5: operation before '(' needed
若當前位置編碼為1,當下一個為1時輸出error code 6: operation after 'x' needed,x為當前位置的資料
若當前位置編碼為4,當下一個為4時輸出error code 7: double operation 'x' 'y',x為當前操作符,y為下一個
若當前位置編碼為4,當下一個不存在時輸出error code 8: extra end operation 'x',x為當前操作符
若當前位置編碼為4,當上一個不存在時輸出error code 9: extra start operation 'x',x為當前操作符
繼續輸入下一組資料
3.若沒有錯誤,則證明是正確的格式。那麼就開始運算。
1)首先是表示式的轉化,將中綴表示式轉化為字尾表示式。
2)利用字尾表示式的計算函式計算結果。但需注意:
當呼叫'/'是需檢測除數是否為0。
若為0,則輸出error code 10:'0' under '/'
為了實現這一功能,使用遞迴的字尾表示式計算函式難以操作,需要考慮新的操作方法。
已知完整的字尾表示式存放在一個棧中,可以建立一個新棧,資料時存入,操作符時操作後壓入棧頂,為'/'時檢測棧頂是否為0。
最後輸出棧頂元素。正常情況下輸出後棧應該只有一個元素。若棧中有多個元素:
extra code 11:BUG SHOWED!DAMN!!!
由於錯誤判斷有很多,決定定義一個全域性變數Error用來儲存是否出現了問題。
在這裡發現了新的問題。之前的文章中轉化為字尾表示式方式無法相容識別負數,於是增加了一些內容用於識別負數。
以上是計算思路。
下面是計算函式的程式碼實現:
1.首先是用資料串替換字母串。
1 int Error=0; 2 3 void givenum(){ 4 Error=0; 5 for (int i=0;i<=x;i++){ 6 if ((all[i][0]>='0'&&all[i][0]<='9')|| 7 all[i]=="("|| 8 all[i]==")"|| 9 all[i][0]=='+'|| 10 all[i][0]=='-'|| 11 all[i]=="*"|| 12 all[i]=="/"){ 13 continue; 14 } 15 if (cnt.find(all[i])!=cnt.end()){ 16 all[i]=cnt[all[x]]; 17 } 18 else{ 19 printf("out>>error code 3: undefined '%s'\n",all[i].c_str()); 20 Error=1; 21 break; 22 } 23 } 24 }
2.檢查表示式合法性。
1 void check(){ 2 Error=0; 3 int code[x+10]; 4 for (int i=0;i<=x;i++){ 5 if (all[i]=="+"|| 6 all[i]=="-"|| 7 all[i]=="*"|| 8 all[i]=="/"){ 9 code[i]=4; 10 continue; 11 } 12 if (all[i][0]=='('){ 13 code[i]=2; 14 continue; 15 } 16 if (all[i][0]==')'){ 17 code[i]=3; 18 continue; 19 } 20 code[i]=1; 21 } 22 if (code[0]==4){ 23 printf("out>>error code 9: extra start operation '%s'\n",all[0].c_str()); 24 Error=1; 25 } 26 for (int i=0;i<=x;i++){ 27 if (i>0&& 28 code[i]==1&& 29 code[i-1]==3){ 30 printf("out>>error code 4: operation after ')' needed\n"); 31 Error=1; 32 } 33 if (i<x&& 34 code[i]==1&& 35 code[i+1]==2){ 36 printf("out>>error code 5: operation before '(' needed\n"); 37 Error=1; 38 } 39 if (i<x&& 40 code[i]==1&& 41 code[i+1]==1){ 42 printf("out>>error code 6: operation after '%s' needed\n",all[i].c_str()); 43 Error=1; 44 } 45 if (i<x&& 46 code[i]==4&& 47 code[i+1]==4){ 48 printf("out>>error code 7: double operation '%s' '%s'\n",all[i].c_str(),all[i+1].c_str()); 49 Error=1; 50 } 51 } 52 if (code[x]==4){ 53 printf("out>>error code 8: extra end operation '%s'\n",all[x].c_str()); 54 Error=1; 55 } 56 }
3.轉化表示式。
1 stack<string> fx1; 2 stack<string> fx2; 3 4 int level(string buffer){ 5 switch (buffer[0]){ 6 case '+': return 1; 7 case '-': return 1; 8 case '*': return 2; 9 case '/': return 2; 10 default: return 0; 11 } 12 } 13 14 void change(){ 15 while (fx1.empty()!=1){ 16 fx1.pop(); 17 } 18 while (fx2.empty()!=1){ 19 fx2.pop(); 20 } 21 int m=0; 22 while (m<=x){ 23 if (all[m]=="+"|| 24 all[m]=="-"|| 25 all[m]=="*"|| 26 all[m]=="/"){ 27 if (fx1.empty()==1|| 28 fx1.top()=="("){ 29 fx1.push(all[m]); 30 m++; 31 continue; 32 } 33 else{ 34 if (level(fx1.top())<=level(all[m])){ 35 fx1.push(all[m]); 36 m++; 37 continue; 38 } 39 else{ 40 while (fx1.empty()!=1&& 41 fx1.top()!="("&& 42 level(fx1.top())>level(all[m])){ 43 fx2.push(fx1.top()); 44 fx1.pop(); 45 } 46 fx1.push(all[m]); 47 m++; 48 continue; 49 } 50 } 51 } 52 if (all[m][0]=='('|| 53 all[m][0]==')'){ 54 if (all[m][0]=='('){ 55 fx1.push(all[m]); 56 m++; 57 continue; 58 } 59 if (all[m][0]==')'){ 60 while (fx1.empty()!=1&& 61 fx1.top()!="("){ 62 fx2.push(fx1.top()); 63 fx1.pop(); 64 } 65 fx1.pop(); 66 m++; 67 continue; 68 } 69 } 70 fx2.push(all[m]); 71 m++; 72 } 73 while (fx1.empty()!=1){ 74 fx2.push(fx1.top()); 75 fx1.pop(); 76 } 77 while (fx2.empty()!=1){ 78 fx1.push(fx2.top()); 79 fx2.pop(); 80 } 81 }
測試這三段程式碼用的主函式是:
1 int main(){ 2 while (1){ 3 Getdata(); 4 if (flag==1){ 5 printf("out>>error code 1:extra ')'\n"); 6 continue; 7 } 8 if (flag==2){ 9 printf("out>>error code 2:extra '('\n"); 10 continue; 11 } 12 if (flag==3){ 13 printf("out>>%s\n",cnt[all[x-1]].c_str()); 14 continue; 15 } 16 if (flag==4){ 17 break; 18 } 19 if (flag==0){ 20 printf("out>>"); 21 for (int i=0;i<x;i++){ 22 printf("%s ",all[i].c_str()); 23 } 24 printf("%s\n",all[x].c_str()); 25 givenum(); 26 if (Error==1){ 27 continue; 28 } 29 check(); 30 if (Error==1){ 31 continue; 32 } 33 change(); 34 while (fx1.empty()!=1){ 35 printf("%s",fx1.top().c_str()); 36 printf(" "); 37 fx1.pop(); 38 } 39 printf("\n"); 40 continue; 41 } 42 } 43 return 0; 44 }
執行結果與預期相同。
到這裡已經達成的目的是將表示式轉化為完整無誤的字尾表示式。
輸出時要注意是否有除數為0的情況出現。
在Part 3中記錄計算輸出結果的模組。