基本思想:使用getline函數從TXT文件中依次讀出中綴表達式,將其轉為後綴表達式後計算結果,並與用戶結果比對。
整數、分數、小數的處理:將小數和整數都視為默認分母為1的分數.建立分數類,在中綴轉換成後綴時將整數和小數轉換為分數.
class Fenshu { private: int fz; int fm; public: int getfz(){ return fz; } int getfm(){ return fm; } void setfz(int FZ){ fz=FZ; } void setfm(int FM){ if(FM!=0) fm=FM; else cout<<"分母不能為0\n"; } Fenshu(){ fz=-1; fm=-1; } Fenshu(int a,int b){ fz=a; if(b!=0) fm=b; else cout<<"分母不能為0\n"; } int gcd(int a, int b)//求最大公約數 { if(b == 0) return a; return gcd(b, a % b); } void yuefen(){//約分 int Gcd=1; Gcd=gcd(fz,fm); //cout<<"GCD:"<<Gcd<<endl; fz=fz/Gcd; fm=fm/Gcd; // cout<<"results:";show();//test } Fenshu operator+(Fenshu F) { return Fenshu(fz*F.fm+F.fz*fm,fm*F.fm); } Fenshu operator-(Fenshu F) { return Fenshu(fz*F.fm-F.fz*fm,fm*F.fm); } Fenshu operator*(Fenshu F) { return Fenshu(fz*F.fz,fm*F.fm); } Fenshu operator/(Fenshu F) { return Fenshu(fz*F.fm,fm*F.fz); } void show(){ cout<<fz<<"/"<<fm<<endl; } };
關於求最大公約數所使用的輾轉相除法在上一篇博文中已經寫過。為了之後代碼書寫方便,使用了重載。
中綴轉換成後綴的處理:使用棧作為數據結構.
template <class ElemType> class MyStack { public: const static int MAXSIZE =100; ElemType data[MAXSIZE]; int top;//棧頂腳標 public: void init(); // 初始化棧 bool empty(); // 判斷棧是否為空 ElemType gettop(); // 讀取棧頂元素(不出) void push(ElemType x); // 進棧 ElemType pop(); // 出棧 };
遇到的問題:
1.分數類定義是分子和分母作為int型變量,題目中出現的小數不能運算;
分析:要將小數轉換成可存進分數的整數,小數點後每有一位,分子分母同乘10,
// 將數字字符串轉變成相應的數字 Fenshu read_number(char str[],int *i) { Fenshu x(0,1); int k = 0; while(str[*i] >='0' && str[*i]<='9') // 處理整數部分 { x.setfz(x.getfz()*10+(str[*i]-'0') ); (*i)++; } if(str[*i]=='.') // 處理小數部分 { (*i)++; while(str[*i] >= '0'&&str[*i] <='9') { x.setfz(x.getfz()*10+(str[*i]-'0')); x.setfm(x.getfm()*10); (*i)++; k++; } } return x; }
2.對於存在負號'-'的題目提示棧為空;
分析:負號與減號的字符同為'-',導致在中綴轉後綴時負號與減號進行了相同的操作(彈出兩個棧頂的操作數)導致操作數錯誤操作;
解決方法:找出作為負號使用的'-',轉換時替換成別的符號寫入後綴表達式.計算後綴表達式時,將該符號後的數字作為0的減數壓入棧
//修正負號的場合 if (pre[i]=='-') // 負號使用場合 { if(pre[i-1]<'0' || pre[i-1]>'9' || pre[i-1]=='(' || i==0) { post[j++]='_'; i++; continue; } }