TXT四则运算计算器
基本思想:使用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; } }