基本思想:使用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;
}
}