CSP201912-3化学方程式
思路分析
每輸入一個方程式即處理一個方程式,這樣可以減少存儲開銷。對輸入的方程式,將其進行多次切分,首先以“=”為界限,將方程式切分為左半部分和右半部分。此操作在主函數(shù)中進行。再對這兩部分,以“+”為界限分別進行切割,此時切割出來的稱為基本項。此操作在如下函數(shù)中進行。
對每一個基本項進行處理,首先提取出基本項的系數(shù),比如說4Na(Au(CN)2)的系數(shù)是4,Na(OH)2的系數(shù)是1,。將系數(shù)分離出來之后,得到的就是化學式,上面給出的兩個基本項提取系數(shù)后得到的化學式分別為Na(Au(CN)2)和NA(OH)2。再遍歷化學式的每一個字符,分為如下幾種情況。
若當前遍歷到的字符是大寫字母,則判斷下一個字符是否為小寫字母,從而得到原子式。之后再提取該原子的下標。
若當前遍歷到的字符是’(’,則進入遞歸處理函數(shù)。遞歸的操作是若遇到’)‘則結(jié)束當前函數(shù),若遇到’('則繼續(xù)進行遞歸,遇到大寫字母則提取其原子式。
本程序的關鍵就是對括號情況的處理,把括號問題解決之后,其余的就都是一些細節(jié)問題了。
上面給出的源碼在CCF系統(tǒng)中經(jīng)過測試是一百分,但這并不是我最初的代碼。剛開始時我是用的結(jié)構(gòu)體存儲的原子,對括號的處理也沒有采用遞歸,而是采用了一種棧的思想。比如說化學式Na(Au2(O(CN3)2S)3,在對其每個字符進行遍歷時,當遍歷到’(’,則把它的位置入棧,遍歷到’)’,則彈出棧頂元素,因為沒分離出一個原子,就把它順序的存儲到結(jié)構(gòu)體數(shù)組中,因此這樣就可以定位到括號內(nèi)的原子。之后再提取括號的下標,讓括號內(nèi)的每個原子的原子數(shù)都乘以下標。當時按照這種方法寫出的程序卻之后90分,找了好長時間也沒發(fā)現(xiàn)問題在那兒,下面給出源碼,還望大神指正。
#include <iostream> #include<string> #include<vector> #include<stack> #include<algorithm> using namespace std; struct Atom {string name;int amount; }; Atom atomL[1000],atomR[1000];//方程左側(cè)的原子和右側(cè)的原子 int countL = 0, countR = 0;//方程式左邊的元素種類數(shù)和右邊的元素種類數(shù) void AddToLeft(Atom a) {int i;for ( i = 0; i < countL; i++) {if (a.name == atomL[i].name) {atomL[i].amount += a.amount;break;}}if (i == countL) {atomL[i].name = a.name;atomL[i].amount = a.amount;countL++;} } void AddToRight(Atom a) {int i;for (i = 0; i < countR; i++) {if (a.name == atomR[i].name) {atomR[i].amount += a.amount;break;}}if (i == countR) {atomR[i].name = a.name;atomR[i].amount = a.amount;countR++;} } //處理方程式的每一項 void ProcessFormula(string coefFormula,char side) {size_t indx = 0;//字符串進行數(shù)值轉(zhuǎn)換時,存放轉(zhuǎn)換過程中第一個不被接受的字符的索引int coef = 1;//系數(shù)string formula;//分子式try {coef = stoi(coefFormula,&indx,10);}catch (exception e){}formula = coefFormula.substr(indx);vector<Atom> formulaAtom;//當前分子式所含的原子stack<int> bracket;//存放左括號的位置int index = 0;//處理分子式時的索引int count = 0;//記錄有多少種原子string atom;while (index < formula.size()) {atom = formula.substr(index, 1);index++;if (atom == "(") {bracket.push(count);}else if (atom == ")") {string temp = formula.substr(index);int num = 1;try {num = stoi(temp, &indx, 10);index += indx;}catch (exception e) {}if (num != 1) {for (int i = bracket.top(); i < count; i++) {formulaAtom[i].amount *= num;}bracket.pop();}}else {string str;str = formula.substr(index, 1);if (str[0] >= 'a'&&str[0] <= 'z') {//判斷緊鄰的下一個字符是否為小寫字母atom += str;index++;}string temp = formula.substr(index);int num = 1;try {num = stoi(temp, &indx, 10);index += indx;}catch (exception e) {}Atom tempAtom = { atom,num };formulaAtom.push_back(tempAtom);count++;}}for (int i = 0; i < count; i++) {formulaAtom[i].amount *= coef;if (side == 'l')AddToLeft(formulaAtom[i]);elseAddToRight(formulaAtom[i]);} } //將方程式的每一項拆分開 void ProcessExpr(string expr,char side) {int start = 0, end;//充當切分方程時的索引值string coefFormula;//系數(shù)和分子式while (true) {end = expr.find('+', start);if (end == -1) {//只剩下最后一項coefFormula = expr.substr(start);ProcessFormula(coefFormula, side);break;}coefFormula = expr.substr(start, end - start);ProcessFormula(coefFormula,side);start = end + 1;} } bool compare(Atom a1, Atom a2) {if (a1.name < a2.name)return true;else return false; } //判斷方程是否配平 bool Judge() {if (countL == countR) { sort(atomL, atomL + countL,compare);sort(atomR, atomR + countR,compare);for (int i = 0; i < countL; i++) {if (atomL[i].name != atomR[i].name || atomL[i].amount != atomR[i].amount)return false;}return true;}elsereturn false; } int main() {int n;cin >> n;char result[100];//存放最后的判斷結(jié)果for (int i = 0; i < n; i++) {countL = countR = 0;string equation;cin >> equation;string left, right;//將方程式以‘=’為界限,分為左半部分和右半部分int position = equation.find('=', 0);left = equation.substr(0, position);right = equation.substr(position+1);ProcessExpr(left, 'l');ProcessExpr(right, 'r');if (Judge())result[i] = 'Y';elseresult[i] = 'N';}for (int i = 0; i < n; i++)cout << result[i] << endl; }附測試用例
H2+O2=H2O 2H2+O2=2H2O H2+Cl2=2NaCl H2+Cl2=2HCl CH4+2O2=CO2+2H2O CaCl2+2AgNO3=Ca(NO3)2+2AgCl 3Ba(OH)2+2H3PO4=6H2O+Ba3(PO4)2 3Ba(OH)2+2H3PO4=Ba3(PO4)2+6H2O 4Zn+10HNO3=4Zn(NO3)2+NH4NO3+3H2O 4Au+8NaCN+2H2O+O2=4Na(Au(CN)2)+4NaOH Cu+As=Cs+Au總結(jié)
以上是生活随笔為你收集整理的CSP201912-3化学方程式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年中考英语计算机考试,2020年
- 下一篇: linux can总线接收数据串口打包上