计算器的改良(NOIP2000)

题目链接:计算器的改良
这道题,不是很难,但代码也短不到哪去。
我们这里决定采取边读入边计算的方法,因为题目没有明确说式子有多长。
我们需要计算什么?
我们需要知道等号两边未知数的系数和常数项即可。
那么我们就要分五种情况去处理:
数字,加号,减号,等号和未知数。
今天我们先看代码,我再来讲思路。

#include<bits/stdc++.h>
using namespace std;
int main(){
    char c;               //用于读入字符
    int lxs=0,rxs=0;    //未知数左边系数和右边系数
    int lcs=0,rcs=0;      //左边常数和右边常数
    int lor=0;           //在左边还是右边的标识符
    int num=0;           //用于保存当前操作数
    int opera=0;         //操作标识符(0是加,1是减)//1
    char x;              //保存未知数
    while(scanf("%c",&c)!=EOF){     //每次读入一个字符
        if(c>='0'&&c<='9'){         //如果是数字
            num=num*10+c-'0';        //2
        }else if(c=='+'){           //如果是加号
            if(lor==0){           //判断是在等号左边还是右边
                if(opera==0){      //判断操作标识符
                    lcs+=num;
                }else{
                    lcs-=num;
                }
            }else{
                if(opera==0){
                    rcs+=num;
                }else{
                    rcs-=num;
                }
            }
            num=0;                  //操作数设置为0
            opera=0;                
        }else if(c=='-'){
            if(lor==0){
                if(opera==0){
                    lcs+=num;
                }else{
                    lcs-=num;
                }
            }else{
                if(opera==0){
                    rcs+=num;
                }else{
                    rcs-=num;
                }
            }
            num=0;
            opera=1;
        }else if(c=='='){
            if(lor==0){             
                if(opera==0){
                    lcs+=num;
                }else{
                    lcs-=num;
                }
            }else{
                if(opera==0){
                    rcs+=num;
                }else{
                    rcs-=num;
                }
            }
            num=0;
            opera=0;
            lor=1;            //转变等式方位
        }else if(c>='a'&&c<='z'){    //如果是字母
            x=c;                   //保存未知数
            if(num==0){
                num=1;
            }
            if(lor==0){
                if(opera==0){
                    lxs+=num;
                }else{
                    lxs-=num;
                }
            }else{
                if(opera==0){
                    rxs+=num;
                }else{
                    rxs-=num;
                }
            }
            num=0;
        }
    }
    if(num!=0){           //3    
        if(opera==0){
            rcs+=num;
        }else{
            rcs-=num;
        }
    }
    double ans=(double)(rcs-lcs)/(double)(lxs-rxs);
    if(ans==0.0){                    //4
        ans=abs(ans);
    } 
    printf("%c=%.3f",x,ans);            //5
    return 0;
}

这里我主要讲一下每一种情况的操作是为什么。
首先遇到数字,我们就将他保存在操作数,为什么不操作?因为我们只读了一个数字,不能确保后面没有数字,而他们是同一个数,所以我们只把新读的数字加到操作数的末尾。
遇到加减时,如果操作数为0,那么操作一次也没影响,但如果操作数不为0,那么说明这肯定时个常数,因为如果是未知数的系数,那么会在读到未知数时进行操作,并被置为0,所以我们只要将对应的常数进行操作就行了,然后设置一下操作标识符。
遇到等于号时,和加减一个意思,只是要将lor该为1,表明进入等式右边。
遇到未知数,第一步,保存下来,为了后面的输出。第二步,系数操作,因为这一定时未知数前的系数。
最后出循环时,还需要判断一下num是不是0,如果不是0,说明式子末尾的常数未操作,因为他后面没有任何字符,所以再判断一下。
这就是设计思路。
下面,我就5个点给大家讲讲:
1处:操作默认是加,因为如果第一个数是负的,那么一定会读到一个减号,转变就行了。
2处:将每个数字加到末尾
3处:好像讲过了,那就算了。
4处:这一步很关键,因为c++有个缺陷,就是说,他认为0除以一个负数为-0,那么输出的时候就会出问题,比如洛谷最后一个测试点,所以我们要取的绝对值。
5处:注意输出的格式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值