NOIP2000普及组 计算器的改良 Codevs1015 字符串复杂处理

http://codevs.cn/problem/1015/


题目大意:输入一个字符串,是一个一元一次方程。该方程只有整数、‘+’、‘-’、‘=’ 三个符号,其中‘-’既可以是负号也可以是减号。没有乘除号、括号和小数。常数和未知数之间的相乘,省略乘号或‘·’。要求输出方程的根,保留三位小数。


输入保证该方程合法,有且仅有一个实根。


样例输入 Sample Input

6a-5+1=2-2a

样例输出 Sample Output

a=0.750

大致思路:先确定代表未知数的字母。然后从左到右逐个字符进行讨论。分别存储常数项的和,以及未知数项的系数之和。在等号右边时,移项过后加变减,减变加。

处理较为繁杂,需细心考虑。

直接给出代码。(加了注释之后代码看起来很长。只是看起来)

#include<string>
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
string s;
char x;<span style="white-space:pre">			</span>//表示未知数的字母
double dx=0,dk=0;	//dx记录未知数的各项系数之和,dy记录所有常数项之和 

bool is_alpha(char c)		//判断某个字符是不是字母 
	{if ((c>='a' && c<='z')||(c>='A' && c<='Z')) return true; return false;}
	

bool is_num(char c)			//判断某个字符是不是数字 
	{if (c>='0' && c<='9') return true; return false;}
	

void calc(int f,int sum,bool l,double &add){	//add 采用引用的形式,就不需要讨论加的是dx还是dk了 
	//f表示当前项正负,sum表示当前项常数之和,l表示在等号左边还是右边 
	if (l==1) add+=sum*f;	//如果在等号左边,正常做加减 
	if (l==0) add-=sum*f;	//如果在等号右边,由于移项,加变减,减变加 
}


int main(){
	cin>>s;
	
	//确认代表未知数的字母 
	for (int i=0;i<s.length();i++)
		if (is_alpha(s[i])) {
			x=s[i];break;
		}
		
	
	bool l=1;			//1表示在等号左边 , 0表示在等号右边 
	int f=1;			//1表示当前项为正 , -1表示当前项为负 
	int sum=0;			//当前项的常数值
	
	 
	for (int i=0;i<=s.length();i++){					//取等号是因为把所有字符都讨论完了之后还要再运算一次 
		if (i==s.length()) {calc(f,sum,l,dk); break;}	//如上一行注释所说,如果是最后一次,只做运算,不讨论字符 
		
		char c=s[i];		
		
		//以下每行都写continue是为了整齐一点,不用写else 	
				
		
		//如果是+或者-,之前必定已有一项结束,故先对之前一项进行计算,然后重置f和sum				
		if (c=='-') {calc(f,sum,l,dk); f=-1,sum=0; continue;}
		if (c=='+') {calc(f,sum,l,dk); f= 1,sum=0; continue;}
		
		
		/*如果是未知数,分两种情况:当sum=0时,意味着这个未知数项没有系数,要将系数修正为1;(数据里没有0x这样的项)
		 		当sum!=0时,正常做加减即可。记得计算完之后修正f和sum。这样即使后面跟+或-,对常数的加减也是0,没有影响*/
		if (c== x ) {if (sum==0) sum=1;   calc(f,sum,l,dx); f= 1,sum=0; continue;}
		
		
		//如果是数字,加sum就好了 
		if (is_num(c)) {sum*=10; sum+=c-'0'; continue;}
		
		//碰到等号,修改l的值。不要忘了先进行一次计算 
		if (c=='=') {calc(f,sum,l,dk); l=0,f=1,sum=0; continue;}
	}
	
	
	printf("%c=%.3lf",x,-dk/dx);			//由于以上的操作把常数项和未知数项都放在等号左边,所以求解时要加负号
	 
	return 0;
}


©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值