洛谷 P1022 计算器的改良 题解

祭!!!

至今刷题最大量代码(163行)

不过代码不难理解

我的思路呢,大致如下↓↓↓

将首项和末项以及符号间的单项提取出来(用 substr 函数实现),进行移项(统一将一次项移到左边,常数项移到右边)

再把常数和&&系数和相除

完成这样的操作是个很繁琐的过程

于是我将问题分解写了几个函数


one

确定该方程的未知数符号

char find_char()//查找该方程的未知数 
{
    int i;
    for(i=0;i<len;i++)//len是全局变量 
    {
        if(s[i]>='a'&&s[i]<='z')
        return s[i];
    }
}

 two

将等号的位置记录下来,以便操作

int find_eq()//找到"="的位置 
{
    int i;
    for(i=0;i<len;i++)//len是全局变量
    {
        if(s[i]=='=')
        return i;
    }
}

three

将一个字符串转为整数

int get_shu(string s)//将一个字符串转为整数 
{
    int i,ans=0;
    for(i=0;i<s.size();i++)
    {
        ans*=10;
        ans+=(int)s[i]-'0';
    }
    return ans;    
}

four

判断是否是未知项   说白了,就是判断提取出的子串中有无字母

bool judge(string s)//判断是否是一次项 
{
    int i;
    for(i=0;i<s.size();i++)
    {
        if(s[i]==c)
        return true;
    }
    return false;
}

five

最核心的计算(别看代码长,其实是对称的)

void heart(int f,int b)//计算 
{
    string a=s.substr(f,b-f+1);
    //s.substr(a,b):在字符串s的第a位截取b个字符组成的子串 
    bool p=judge(a);
    if(p)//一次项(含未知项) 
    {
        if(b<=eq)//在等号左边 
        {
            if(a.size()==1)//要考虑系数为一而省略的情况 
            {
              if(s[f-1]=='-')
              xishu--;
              else xishu++;
            }
            
            if(f==0) 
                xishu+=get_shu(s.substr(f,b));//f是0,故b-f=b 
            else
            if(s[f-1]=='-')
            xishu-=get_shu(s.substr(f,b-f)); 
            else xishu+=get_shu(s.substr(f,b-f));
        }
        else//在等号右边 
        {
            if(a.size()==1)
           {
              if(s[f-1]=='-')
              xishu++;
              else xishu--;
           }
            if(f==eq+1)
            xishu-=get_shu(s.substr(f,b-f));
            else
            if(s[f-1]=='-')
            xishu+=get_shu(s.substr(f,b-f));
            else xishu-=get_shu(s.substr(f,b-f));
        }
    }
    
    
    
    else//常数 
    {
           if(b<=eq)//在等号左边
        {
            if(f==0) 
            changshu-=get_shu(s.substr(f,b+1));//与前稍有不同 
            else
            if(s[f-1]=='-')
            changshu+=get_shu(s.substr(f,b-f+1));
            else changshu-=get_shu(s.substr(f,b-f+1));
        }
        
        else//在等号右边
        {
            if(f==eq+1)
                changshu+=get_shu(s.substr(f,b-f+1));
            else
            if(s[f-1]=='-')
            changshu-=get_shu(s.substr(f,b-f+1));
            else changshu+=get_shu(s.substr(f,b-f+1));
        }
    }
}

那就上总体代码吧

#include<bits/stdc++.h>
using namespace std;
string s;
double ans;
int len,i,eq;//eq为"="位置 
char c;
int xishu,changshu;//系数,常数^_^ 

char find_char()//查找该方程的未知数 
{
    int i;
    for(i=0;i<len;i++)//len是全局变量 
    {
        if(s[i]>='a'&&s[i]<='z')
        return s[i];
    }
}

int find_eq()//找到"="的位置 
{
    int i;
    for(i=0;i<len;i++)//len是全局变量
    {
        if(s[i]=='=')
        return i;
    }
}

int get_shu(string s)//将一个字符串转为整数 
{
    int i,ans=0;
    for(i=0;i<s.size();i++)
    {
        ans*=10;
        ans+=(int)s[i]-'0';
    }
    return ans;    
}

bool judge(string s)//判断是否是一次项 
{
    int i;
    for(i=0;i<s.size();i++)
    {
        if(s[i]==c)
        return true;
    }
    return false;
}



void heart(int f,int b)//计算 
{
    string a=s.substr(f,b-f+1);
    //s.substr(a,b):在字符串s的第a位截取b个字符组成的子串 
    bool p=judge(a);
    if(p)//一次项(含未知项) 
    {
        if(b<=eq)//在等号左边 
        {
            if(a.size()==1)//要考虑系数为一而省略的情况 
            {
              if(s[f-1]=='-')
              xishu--;
              else xishu++;
            }
            
            if(f==0) 
                xishu+=get_shu(s.substr(f,b));//f是0,故b-f=b 
            else
            if(s[f-1]=='-')
            xishu-=get_shu(s.substr(f,b-f)); 
            else xishu+=get_shu(s.substr(f,b-f));
        }
        else//在等号右边 
        {
            if(a.size()==1)
           {
              if(s[f-1]=='-')
              xishu++;
              else xishu--;
           }
            if(f==eq+1)
            xishu-=get_shu(s.substr(f,b-f));
            else
            if(s[f-1]=='-')
            xishu+=get_shu(s.substr(f,b-f));
            else xishu-=get_shu(s.substr(f,b-f));
        }
    }
    
    
    
    else//常数 
    {
           if(b<=eq)//在等号左边
        {
            if(f==0) 
            changshu-=get_shu(s.substr(f,b+1));//与前稍有不同 
            else
            if(s[f-1]=='-')
            changshu+=get_shu(s.substr(f,b-f+1));
            else changshu-=get_shu(s.substr(f,b-f+1));
        }
        
        else//在等号右边
        {
            if(f==eq+1)
                changshu+=get_shu(s.substr(f,b-f+1));
            else
            if(s[f-1]=='-')
            changshu-=get_shu(s.substr(f,b-f+1));
            else changshu+=get_shu(s.substr(f,b-f+1));
        }
    }
}


int main()
{
    int ft,bd;
    cin>>s;
    len=s.size();
    c=find_char();
    eq=find_eq();
    
    ft=0; 
    for(i=0;i<=eq;i++)
    {
        if(s[i]=='+'||s[i]=='-'||i==eq)
        {
            bd=i-1;
            heart(ft,bd);
            ft=i+1;
        }
    }
    //等号左右分开操作 
    ft=eq+1; 
    for(i=eq+1;i<=len-1;i++)
    {
        if(s[i]=='+'||s[i]=='-')
        {
            bd=i-1;
            heart(ft,bd);
            
            ft=i+1;
        }
    }
    heart(ft,i-1);//处理最后一项 

    if(changshu==0) 
    {
        cout<<c<<"=0.000";
        return 0;
    }
    ans=(double)changshu/xishu;
    cout<<c<<"=";
    printf("%.3f",ans);
    return 0;
}

好吧,是有点长,模拟题嘛

猜你喜欢

转载自www.cnblogs.com/zhouzhihao/p/10367004.html