CCF-19-12-3化学方程式(超简洁满分代码)

#include<iostream>
#include<sstream>
#include<vector>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
int toNumber(string item,int &pos) {
	int num = 0;
	while (isdigit(item[pos])) {	//循环判断数字的位数
		num = num * 10 + item[pos] - '0';
		pos++;
	}
	return num;
}
struct Elem {//元素
	string name;//名称
	int num;//个数
	Elem(string _name, int _num) :name(_name), num(_num) {}
};
void calc(string& str, map<string, int>& mp) {
	stringstream ss(str);
	string item;
	while (getline(ss, item, '+')) {//以'+'分割获得单项式
		int preNum=1;				//单项式前置系数,默认为1
		int i = 0;					//充当单项式中指针,记录单项式处理到第几位了
		vector<Elem>arr;
		if (isdigit(item[0])) 
			preNum = toNumber(item,i);//记录单项式系数
		
		while (i != item.size()) {	//处理单项式内部元素

			
			if (isdigit(item[i])) {		//遇到数字
				int num = toNumber(item, i);
				if (arr[arr.size() - 1].name == ")") {//若上一个为右括号,则把前面到最近一个左括号的元素全部累乘
					int j = arr.size() - 1;
					arr[j].name = "*";//将右括号标记为*,代表已经处理过该右括号
					while (arr[--j].name != "(") {//向前循环
						arr[j].num *= num;
					}
					arr[j].name = "*";
				}
				else {
					arr[arr.size() - 1].num *= num;//若没有右括号则只把前一个元素的个数累成
				}
			}	
			else if (isupper(item[i])) {//遇到大写字母
				string name = "";
				name = item[i++];
				if (islower(item[i])) {	//若同时下一个为小写字母
					name += item[i++];
				}
				arr.push_back(Elem(name, 1));
			}
			else if (item[i] == '(') {	//遇到左括号
				arr.push_back(Elem("(", 1));
				i++;
			}
			else if (item[i] == ')') {	//遇到右括号
				arr.push_back(Elem(")", 1));
				i++;
				if (!isdigit(item[i])) {
					item.insert(i,"1");
				}
			}	
		}	
		for (int j = 0; j != arr.size(); j++) {//将元素个数储存到map中,
			if (arr[j].name == "*")
				continue;
			else
				mp[arr[j].name] += arr[j].num * preNum;//"+="是因为同一元素可能会出现在不同单项式中
		}
	}		
}		
bool judge(map<string, int>& left, map<string, int>& right) {
	if (left.size() != right.size())
		return false;
	else {
		for (map<string, int>::iterator it = left.begin(); it != left.end(); it++) {
			if (right[it->first] != it->second)
				return false;
		}
	}
	return true;
}
int main() {
	int n;
	
	
	cin >> n;
	for (int i = 0; i < n; i++) {
		stringstream ss;//使用文件流,方便进行字符分割
		string str, lstr, rstr;
		map<string, int> left, right;
		cin >> str;
		ss.str(str);
		getline(ss, lstr, '=');	//getline每次读取一行输入,默认以换行符作为分割,,也可以指定'='作为代替换行符
		getline(ss, rstr);		//不输入则默认换行符作为分割,即3Ba(OH)2+2H3PO4=Ba3(PO4)2+6H2O\n 被分别读取到了lstr和rstr中
		
		calc(lstr, left);
		calc(rstr, right);
		if (judge(left, right))
			cout << "Y" << endl;
		else
			cout << "N" << endl;
	}
	return 0;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值