洛谷 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; }
好吧,是有点长,模拟题嘛
标签:&&,洛谷,string,int,题解,char,P1022,eq,find 来源: https://www.cnblogs.com/zhouzhihao/p/10367004.html