题解 P1022 [计算器的改良]

· · 题解

这道题坑点很多。这里提供一个较为巧妙的做法。

我们其实不用人工移项、合并等操作。

思路:将所有项移到等号左边,最后答案为常数项系数与一次项系数的商的相反数。(很好理解)

用sign代表等号左边或右边,fh表示符号。当搜到未知数(设为x)时,一次项系数 + (当前系数)num * sign * fh;当搜到+ - =时,更新常数项系数。具体见代码。

#include <cstdio>
#include <cstdlib>
#include <cstring>

char c;                        //读取当前字符
int sign = 1;                //sign,表示等号左边(1)与右边(-1)
int num = 0;                //当前数
int xnum = 0;                //一次项系数
int onum = 0;                //常数项系数
char zm = 'x';                //未知数
int fh = 1;                    //符号

int main()
{
    while (1)
    {
        c = getchar();        //读取一个字符
        if (c == '\r')        //如果是回车就结束。注意windows里是\n,Linux里是\r
        {                    //更新当前常数项系数
            onum += num * sign * fh;
            break;
        }
        else if (c == '=')    //等号,更改sign,更新常数项系数
        {
            sign = -1;
            onum += num * fh;
            num = 0;
            fh = 1;            //默认符号是正
        }
        else if (c == '-')    //减号,同上
        {
            onum += num * sign * fh;
            num = 0;
            fh = -1;
        }
        else if (c == '+')    //加号,同上
        {
            onum += num * sign * fh;
            num = 0;
            fh = 1;
        }                    //数字符号,更新num
        else if (c >= '0' && c <= '9')
        {
            c -= '0';
            num = num * 10 + c;
        }
        else                 //更新未知数
        {
            zm = c;
            if (num == 0)    //接地气地符合数学表示习惯
                xnum += fh * sign;
            else
                xnum += num * sign * fh;
            num = 0; fh = 0;
        }
    }
                            //计算答案
    double x = - (double (onum) / double (xnum));
    if (x == 0) x = 0;        //C++尿性
    printf ("%c=%.3lf\n", zm, x);
}