题解 P1022 【计算器的改良 】

teafrogsf

2017-08-24 16:20:37

Solution

## 此题不需要代码很长的模拟。 我们首先可以~~敏锐地~~发现,+的ASCII码值为43,-的ASCII码值为45,于是在判断是+还是-时,只需要算s[i]-44再乘个-1就可以了。 所有加减操作都可以在一个if里解决——当判断到符号时,**用存好的上一个符号结算在这个符号之前的那个数。**这种方法主要的难点是**特判**。 ### ① 读入 读入的时候从1开始,0的位置添加一个加号,方便计算。循环中判定一下字母是什么。 ### ② 等于号 检查到等于号时,将lor从1变为-1。\_lor是用于切换在方程左边还是右边的int。\_等于号直接变为加号就可以了,注意存一下等于号的位置。 ### ③ 结果 将分子(整数和)和分母(未知数系数和)放在方程两边(在计算时的实现是son比mother**多乘一个-1**),直接相除即可。 ### ④ 0 当一个未知数前面只有一个负号或正号(比如-x),系数为±1。需进行特判。同时,若这个数是0则它就是0,不能修改它。这一点详见代码,我是用是否走过循环来判定的。 ### ⑤ 0.0(C/C++) ~~上面这个东西并不是表情符号。~~当0除以一个负数时,C/C++会默认将其判断成-0.0。所以要特判一下。 ### ⑥ 计算过程 公式是son=x\*lor\*-1\*(s[pre]-44)\*-1,mother少一个-1。 ### ⑦ 代码 如下。 ```cpp #include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define f(i,a,b) for(register int i=a;i<=b;++i) bool flag,havenum; char s[100010],ansx; int son,mother,pre,lor=1,equal; int main() { int len; scanf("%s",s+1); s[pre]='+';len=strlen(s+1);s[len+1]='+';//随便一个符号都可以 f(i,1,len+1) { if(s[i]>='a'&&s[i]<='z')ansx=s[i]; if(s[i]=='='||s[i]=='-'||s[i]=='+') { havenum=0; if(i==1||i-1==equal){pre=i;continue;} int j,x=0; if(isdigit(s[i-1]))flag=0; else flag=1; for(j=pre+1;j<=i-1-flag;++j) {x=(x<<1)+(x<<3)+(s[j]^'0');havenum=1;} if(havenum==0)x=1; if(flag==0)son+=x*lor*-1*(s[pre]-44)*-1; else mother+=x*lor*(s[pre]-44)*-1;//ASCII - 45 + 43 //printf("%d %d %d %d\n",i,x,son,mother); pre=i; if(s[i]=='=')lor=-1,s[i]='+',equal=i; } }double ansy=double(son)/double(mother);if(fabs(ansy)-0.0<0.000001)ansy=0.0; printf("%c=%.3lf",ansx,ansy);return 0; } ```