【應用】浮點數四則運算器 Part1 輸入模組的編寫
下面首先記錄浮點數四則運算器輸入模組的編寫。
思路和要求記錄如下:
全域性變數:
string dat--儲存正在輸入的串
string all[]--儲存輸入完成的串
map用於計數
flag用於記錄應該執行哪一種輸出模式
x用於記錄已經輸入的資料的個數
一、對輸入資料的預處理。
用getchar輸入,儲存到string中。會出現以下一些情況:
1.輸入了' ':一個串輸入完成,儲存,清空後輸入新的串。
2.輸入了\n':輸入完成了一個表示式,本次輸入結束。
3.過程中輸入了'=':說明這是變數賦值語句,應該輸出變數的值。
4.輸入的串為"exit":說明計算完成,程式停止。
5.其他情況則儲存字元。
其中,1. 2. 4. 5.都易於實現,而對於3. 可以採用將等號之前的部分儲存為一個串,等號之後的部分儲存為另一個串,後續使用map處理。
!6.這裡可以進行的表示式錯誤型別判斷:括號的匹配。
可這樣進行:令code=0,當輸入'('時code1++;當輸入')'時code--; 用這樣的邏輯,我們可以區分出以下情況:
1)輸入結束時flag<0,說明有')'多餘,flag=1,記為error code 1:extra ')'。
2)輸入結束時flag>0,說明有‘('多餘,flag=2,記為error code 2:extra '('。
輸入模組(包括標頭檔案)程式碼嘗試編寫:
1 #include<iostream> 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 #include<map> 6 #include<stack> 7 #include<queue> 8 9 using namespace std; 10 11 string dat; 12 string all[100]; 13 map<string,double> cnt;14 map<string,double>::iterator iter; 15 int flag=0; 16 int x=0; 17 18 void Getdata(){ 19 x=0; 20 flag=0; 21 dat=""; 22 for (int i=0;i<100;i++){ 23 all[i]=""; 24 } 25 int code=0; 26 char a=0; 27 cout<<"in>>"; 28 while (1){ 29 a=getchar(); 30 if (a=='('){ 31 code++; 32 } 33 if (a==')'){ 34 code--; 35 } 36 if (a==' '){ 37 all[x]=dat; 38 x++; 39 dat=""; 40 continue; 41 } 42 if (a=='\n'){ 43 all[x]=dat; 44 dat=""; 45 if (flag==3){ 46 cnt[all[x-1]]=atof(all[x].c_str()); 47 } 48 if (all[x]=="exit"){ 49 flag=4; 50 } 51 if (code<0){ 52 flag=1; 53 } 54 if (code>0){ 55 flag=2; 56 } 57 return ; 58 } 59 if (a=='='){ 60 flag=3; 61 all[x]=dat; 62 x++; 63 dat=""; 64 continue; 65 } 66 dat+=a; 67 } 68 }
測試這一段輸入模組的測試用主程式:
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>>%.2lf\n",cnt[all[x-1]]); 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 continue; 26 } 27 } 28 return 0; 29 }
執行結果與預期相同。
這裡意識到可以增加運算器的功能——給多個變數名賦同一個值。
於是將輸入模組程式碼中的第45行到47行修改為:
1 if (flag==3){ 2 for (int i=0;i<x;i++){ 3 cnt[all[i]]=atof(all[x].c_str()); 4 } 5 }
這樣就同時給多個同樣數值的變數賦了同一個值。
(我喜歡寫每一行內容很少行數很多的程式碼……捂臉……因為看起來整齊)
二、對輸入資料的運算過程。(初步規劃)
首先記錄一下已經輸入好的資料的儲存位置。
·cnt[all[i]]儲存了在exit之前的所有的變數值,以最後一次輸入為準。 map類
·all[300]中儲存了每一次輸入後所有的資料。 string類
·x記錄了all中資料的個數,一直到all[x]都有資料填充。 int類
現在all[300]中儲存了可能含有字母元的中綴表示式,可以將其轉化為字首表示式後運算輸出結果。
到這裡已經基本結束了,轉化方法和運算方法在 【資料結構】棧與佇列Part2:棧的應用之表示式轉換 已經有所操作。
但是還有一個遺留的問題:錯誤型別的判斷。
期望能做到的有:
1.能夠識別除數是否為0。
2.能夠識別是否出現了不合法運算式,比如5 6 * 3,這裡5和6中間缺少運算子。
PLUS:能夠識別缺少運算子的位置。
3.能夠識別沒有賦初值的字母元。
由於資料的儲存方式,2和3都很容易實現,但1的識別依然是一個難點。
想到的解決方式是運算過程遇到'/'時檢測被除數。
這樣基本就可以編輯出完整的浮點數四則運算器。
Part2將會是運算輸出模組的編寫和執行。