1. 程式人生 > >【應用】浮點數四則運算器 Part1 輸入模組的編寫

【應用】浮點數四則運算器 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將會是運算輸出模組的編寫和執行。