csp 201912-3 化学方程式
程序员文章站
2022-05-12 14:54:38
...
解答:(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;
}