csp 201912-3 化学方程式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
解答:(40分未考虑)系数可以是多位数,(70分未考虑)括号嵌套可以是:((化学式))(化学式)。思路按照巴克斯范式分析。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct big{
	int count;
	int small[26];
};// 比如:big['C'-'A'].small['a'-'a'] = 9,表示Ca元素系数9;big['C'-'A'].count = 9,表示C元素系数9; 

typedef struct big big;

void dealEqualSign(char* equation,big* left,big* right);// 处理'='号,得到两个表达式 
void dealPlusSign(char* expr,int which,big* left,big* right);// 处理'+'号,得到每个部分 
void dealPart(char* part,int which,big* left,big* right);// 处理部分,得到ceof
void dealBracket(char* formula,int ceof,int which,big* left,big* right);// 处理括号,得到化学式 
void dealTerm(char* moele,int ceof,int which,big* left,big* right);// 处理化学式,得到元素 
void dealElement(char* term,int size,int ceof,int which,big* left,big* right);// 处理元素 
int judgeLR(big* left,big* right);// 判断是否相等 

int main(){
	int n,i,j,k;
	scanf("%d",&n);
	for(i=0; i<n; i++){
		big left[26],right[26];
		for(j=0; j<26; j++){
			left[j].count = right[j].count = 0;
			for(k=0; k<26; k++){
				left[j].small[k] = right[j].small[k] = 0;
			}
		}
		char equation[1001]={'\0'};
		scanf("%s",equation);
		dealEqualSign(equation,left,right);
		if(judgeLR(left,right) == 1){
			printf("Y\n");
		}else{
			printf("N\n");
		}
	}
	return 0;
}

// 处理'='号,得到两个表达式 
void dealEqualSign(char* equation,big* left,big* right){
	if(equation[0]=='\0') return;
	int i=-1;
	while(equation[++i] != '=');
	equation[i] = '\0';
	dealPlusSign(equation,0,left,right);
	dealPlusSign(equation+i+1,1,left,right);
}

// 处理'+'号,得到每个部分 
void dealPlusSign(char* expr,int which,big* left,big* right){
	if(expr[0]=='\0') return;
	
	int i=0;
	while(expr[i] != '\0' && expr[i] != '+'){
		i++;
	};
	if(expr[i] == '+'){
		expr[i]='\0';
		dealPart(expr,which,left,right);
		dealPlusSign(expr+i+1,which,left,right);
	}else{
		dealPart(expr,which,left,right);
	}
}

// 处理部分,得到ceof
void dealPart(char* part,int which,big* left,big* right){
	if(part[0]=='\0') return;
	int ceof = 0, i=0;
	while('0'<=part[i] && part[i]<='9'){
		ceof = ceof*10+(part[i]-'0');
		i++;
	}
	if(ceof == 0) ceof = 1; 
	dealBracket(part+i,ceof,which,left,right);
} 

// 处理括号,得到化学式 
void dealBracket(char* formula,int ceof,int which,big* left,big* right){
	if(formula[0] == '\0') return;
	int i,lk=-1,rk=-1,rk_t=0,lk_t=0,fsize=strlen(formula);
	for(i=0; i<fsize; i++){
		if(formula[i] == '('){
			if(lk == -1)
				lk=i; // 只要第一个出现的左括号 
			lk_t++;
		}
		if(formula[i] == ')'){
			rk=i; // 要最后一个出现的右括号 
			rk_t++;
		}
		if(lk_t != 0 && lk_t == rk_t) break;
	}
	if(lk != -1){
		formula[lk]='\0';
		dealTerm(formula,ceof,which,left,right);
		
		formula[rk]='\0';
		int ceof2 = 0;
		i = rk+1;
		while('0' <= formula[i] && formula[i] <= '9'){
			ceof2 = ceof2*10+(formula[i]-'0');
			i++;
		}
		if(ceof2 == 0) ceof2 = ceof;
		else ceof2 *= ceof;
		dealBracket(formula+lk+1,ceof2,which,left,right);
		
		dealBracket(formula+i,ceof,which,left,right);

	}else{
		dealTerm(formula,ceof,which,left,right);
	}
}

// 处理化学式,得到元素 
void dealTerm(char* moele,int ceof,int which,big* left,big* right){
	if(moele[0] == '\0') return;
	int msize = strlen(moele);
	int ceof2 = 0,i=1,start=0;
	if(moele[i] >= 'a' && moele[i] <= 'z'){// 元素为大小写字母 
		++i;
		while('0'<=moele[i] && moele[i]<='9'){
			ceof2 = ceof2*10+(moele[i]-'0');
			i++;
		}
		if(ceof2 == 0){ 
			ceof2 = ceof;
		}else{
			ceof2 *= ceof;
		} 
		dealElement(moele,2,ceof2,which,left,right);
		dealTerm(moele+i,ceof,which,left,right);
	}else{
		while('0'<=moele[i] && moele[i]<='9'){
			ceof2 = ceof2*10+(moele[i]-'0');
			i++;
		}
		if(ceof2 == 0){ 
			ceof2 = ceof;	
		}else{
			ceof2 *= ceof;
		}
		dealElement(moele,1,ceof2,which,left,right);
		dealTerm(moele+i,ceof,which,left,right);
	}
}

// 处理元素 
void dealElement(char* term,int size,int ceof,int which,big* left,big* right){
	if(term[0]=='\0') return;
	if(size == 1){
		if(which == 0){
			left[(int)(term[0]-'A')].count += ceof;
		}else{
			right[(int)(term[0]-'A')].count += ceof;
		}
	}else{
		if(which == 0){
			left[(int)(term[0]-'A')].small[(int)(term[1]-'a')] += ceof;
		}else{
			right[(int)(term[0]-'A')].small[(int)(term[1]-'a')] += ceof;
		}
	}
}

// 判断是否相等 
int judgeLR(big* left,big* right){
	int flag = 1,i,j;
	for(i=0; i<26; i++){
		if(left[i].count != right[i].count){
			flag = 0;
			break;
		}
		for(j=0; j<26; j++){
			if(left[i].small[j] != right[i].small[j]){
				flag = 0;
				i = 26;
				break;
			}
		}
	}
	return flag;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值