1. 程式人生 > >【應用】浮點數四則運算器 Part2:轉化模組的編寫

【應用】浮點數四則運算器 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中記錄計算輸出結果的模組。