----化学方程式配平工具----
生活随笔
收集整理的這篇文章主要介紹了
----化学方程式配平工具----
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
(利用待定化學(xué)計(jì)量數(shù)法配平,先根據(jù)每種元素列出方程組,然后解方程組,就可以解出計(jì)量數(shù)之比)
ChemistryEquationStringProcess.h文件:
#pragma once #include <stdio.h> #include <stdlib.h> #include <string.h> #include <memory.h> #include <math.h> #include "EquationSetSolve.h" typedef int BOOL; #define TRUE 1 #define FALSE 0typedef struct _ELEMENT {char Name[128]; //元素名稱;int Num; //數(shù)量;struct _ELEMENT *next; }ELEMENT;typedef struct _SUBSTANCE {char kName[64]; //給系數(shù)設(shè)置元;char Name[128]; //物質(zhì)名稱;char UsedName[128]; //Used Name;ELEMENT *elements; //組成物質(zhì)的元素;struct _SUBSTANCE *next; }SUBSTANCE;typedef struct _SUBSTANCEPOINTER {SUBSTANCE*pAddress;struct _SUBSTANCEPOINTER*next; }SUBSTANCEPOINTER;char kName = 'A'; //每種物質(zhì)前的元;SUBSTANCE *LeftSubsHead = 0; //儲(chǔ)存左邊的物質(zhì); SUBSTANCE *LeftSubsTail = 0;SUBSTANCE *RightSubsHead = 0; //儲(chǔ)存右邊的物質(zhì); SUBSTANCE *RightSubsTail = 0; //儲(chǔ)存右邊的物質(zhì);ELEMENT*AllEleCLas = 0; //儲(chǔ)存所有的元素; int AllEleClasCount = 0; //記錄元素的個(gè)數(shù);SUBSTANCEPOINTER *AllSubsAddrsHead = NULL; //記錄所有元素的地址; SUBSTANCEPOINTER *AllSubsAddrsTail = NULL;char szEquationSet[128]; //儲(chǔ)存生成的方程組; char szEquation[2048]; //儲(chǔ)存方程式; char szRetEquation[2048]; //儲(chǔ)存方程式; char szLeftEqua[1024]; //左部分方程式; char szRightEqua[1024]; //右部分方程式; //是否在元素鏈表中; ELEMENT* InElementList(char*ElementName, ELEMENT*ListHead) {ELEMENT*pEle;for (pEle = ListHead; pEle != NULL; pEle = pEle->next){if (!strcmp(pEle->Name, ElementName))break;}return pEle; }//清空字符數(shù)組; void Init() {memset(szEquation, 0, sizeof(szEquation));memset(szEquation, 0, sizeof(szRetEquation));memset(szLeftEqua, 0, sizeof(szLeftEqua));memset(szRightEqua, 0, sizeof(szRightEqua)); } //分割方程式,失敗反回FALSE,成功返回TRUE; BOOL DevideEquation() {char *p;memset(szLeftEqua, 0, sizeof(szLeftEqua));memset(szRightEqua, 0, sizeof(szRightEqua));p = szEquation;//等號(hào)左邊沒(méi)有東西;if (*p == '=')return FALSE;while (*p != '='&& *p != NULL) p++;//沒(méi)有等于號(hào);if (*p == NULL)return FALSE;//儲(chǔ)存方程式左部分;memcpy(szLeftEqua, szEquation, p - szEquation);//移到方程式右部分開(kāi)始處;while (*p == '='&& *p != NULL) p++;//等號(hào)右邊沒(méi)有東西;if (*p == NULL)return FALSE;//儲(chǔ)存右邊的方程式;strcpy(szRightEqua, p);//方便后面分割各種物質(zhì);strcat(szLeftEqua, "+");strcat(szRightEqua, "+");return TRUE; } //分割各種物質(zhì); BOOL CallDevideSubstance(char*szPartEquation, SUBSTANCE**SubsListHead, SUBSTANCE**SubsListTail) {char*pSubsStart, *pSubsEnd;pSubsStart = pSubsEnd = szPartEquation;while (*pSubsEnd != NULL){//是一種元素的尾端;if (*pSubsEnd == '+'){//添加到SubsList中;//尾為空,頭不存在;if (*SubsListTail == NULL){*SubsListHead = *SubsListTail = (SUBSTANCE*)malloc(sizeof(SUBSTANCE));}//尾不為空,在尾的后面添加;else{(*SubsListTail)->next = (SUBSTANCE*)malloc(sizeof(SUBSTANCE));*SubsListTail = (*SubsListTail)->next;}/*--------------------------------添加到AllSubsAddrsList中----------------------------*/if (AllSubsAddrsTail == NULL){AllSubsAddrsHead = AllSubsAddrsTail = (SUBSTANCEPOINTER*)malloc(sizeof(SUBSTANCEPOINTER));}else{AllSubsAddrsTail->next = (SUBSTANCEPOINTER*)malloc(sizeof(SUBSTANCEPOINTER));AllSubsAddrsTail = AllSubsAddrsTail->next;}AllSubsAddrsTail->next = NULL;AllSubsAddrsTail->pAddress = *SubsListTail;/*-----------------------------------------------------------------------------------*///設(shè)置新SUBSTANCE的值;memset((*SubsListTail)->kName, 0, sizeof((*SubsListTail)->kName));memset((*SubsListTail)->Name, 0, sizeof((*SubsListTail)->Name));memset((*SubsListTail)->UsedName, 0, sizeof((*SubsListTail)->UsedName));(*SubsListTail)->elements = NULL;(*SubsListTail)->next = NULL;*(*SubsListTail)->kName = kName++;//忽略已經(jīng)填寫的系數(shù);while (*pSubsStart >= '0' && *pSubsStart <= '9')pSubsStart++;//常數(shù)項(xiàng),沒(méi)有元素名稱;if (pSubsEnd == pSubsStart)return FALSE;memcpy((*SubsListTail)->Name, pSubsStart, pSubsEnd - pSubsStart);memcpy((*SubsListTail)->UsedName, pSubsStart, pSubsEnd - pSubsStart);pSubsStart = pSubsEnd + 1;}pSubsEnd++;}return TRUE; } BOOL DevideSubstance() {//分割左邊的物質(zhì);if (!CallDevideSubstance(szLeftEqua, &LeftSubsHead, &LeftSubsTail))return FALSE;//分割右邊的物質(zhì);if (!CallDevideSubstance(szRightEqua, &RightSubsHead, &RightSubsTail))return FALSE;return TRUE; } //將點(diǎn)轉(zhuǎn)換為括號(hào); void CallChangePoint(SUBSTANCE*pSubs) {char *pPointStart, *pPointEnd;int value = 0, len = 0;char buff[128] = { 0 };while (1){pPointEnd = pSubs->UsedName;//查找開(kāi)始點(diǎn);while (*pPointEnd != '.' && *pPointEnd != NULL)pPointEnd++;pPointStart = pPointEnd;//不存在點(diǎn);if (*pPointStart == NULL)break;pPointEnd++;//查找結(jié)束點(diǎn);while (*pPointEnd != '.' && *pPointEnd != NULL)pPointEnd++;//開(kāi)始轉(zhuǎn)換點(diǎn);//如果點(diǎn)后面為數(shù)字;if (*(pPointStart + 1) >= '0' && *(pPointStart + 1) <= '9'){//將結(jié)束點(diǎn)后(包括點(diǎn))復(fù)制到buff中;memcpy(buff, pPointEnd, pSubs->UsedName + strlen(pSubs->UsedName) - pPointEnd);//將結(jié)束點(diǎn)后(包括點(diǎn))置為0memset(pPointEnd, 0, pSubs->UsedName + strlen(pSubs->UsedName) - pPointEnd);strcat(pSubs->UsedName, ")");len = StrToNum(pPointStart + 1, &value);//添加數(shù)字到后面;NumToStr(pPointEnd + 1/*多了')',加1*/, value);strcat(pSubs->UsedName, buff);/*-------------------------------*/memset(buff, 0, sizeof(buff));memcpy(buff, pPointStart + len + 1, pSubs->UsedName + strlen(pSubs->UsedName) - (pPointStart + len + 1));memset(pPointStart, 0, pSubs->UsedName + strlen(pSubs->UsedName) - pPointStart);strcat(pSubs->UsedName, "(");strcat(pSubs->UsedName, buff);}else{strcpy(buff, pPointStart + 1);memset(pPointStart, 0, pSubs->UsedName + strlen(pSubs->UsedName) - pPointStart);strcat(pSubs->UsedName, buff);}} } //在個(gè)數(shù)為1的元素后面加'1'; void CallUpdateSubsName(SUBSTANCE*pSubs) {char str[128];int j = 0,i;memset(str, 0, sizeof(str));for (i = 0; i < strlen(pSubs->UsedName); i++){str[j] = pSubs->UsedName[i];j++;if ((pSubs->UsedName[i] >= 'a'&&pSubs->UsedName[i] <= 'z') ||(pSubs->UsedName[i] >= 'A'&&pSubs->UsedName[i] <= 'Z')){//當(dāng)前元素結(jié)尾沒(méi)有數(shù)字;if ((pSubs->UsedName[i + 1] >= 'A'&&pSubs->UsedName[i + 1] <= 'Z') ||pSubs->UsedName[i + 1] == 0 ||pSubs->UsedName[i + 1] == '(' ||pSubs->UsedName[i + 1] == ')'){str[j] = '1';j++;}}}memset(pSubs->UsedName, 0, sizeof(pSubs->UsedName));strcpy(pSubs->UsedName, str); } //去除物質(zhì)中的括號(hào); BOOL RemoveParentheses(SUBSTANCE*pSubs) {char buff[128];char*pParenthesesLeft, *pParenthesesRight;while (1){pParenthesesLeft = pParenthesesRight = pSubs->UsedName;//轉(zhuǎn)移到最內(nèi)層括號(hào)處;while (*pParenthesesRight != ')'&&*pParenthesesRight != NULL){if (*pParenthesesRight == '(')pParenthesesLeft = pParenthesesRight;pParenthesesRight++;}//沒(méi)有右邊括號(hào);if (*pParenthesesRight == NULL){//但是還有左邊括號(hào);if (*pParenthesesLeft == '(')//不匹配;return FALSE;//正常,沒(méi)有括號(hào),退出循環(huán);break;}//找到右括號(hào),但左面無(wú)括號(hào),錯(cuò)誤;if (*pParenthesesLeft != '(')return FALSE;//括號(hào)右邊為數(shù)字;if (*(pParenthesesRight + 1) >= '0'&&*(pParenthesesRight + 1) <= '9'){char *p;int Value, Len;Len = StrToNum(pParenthesesRight + 1, &Value);memset(buff, 0, sizeof(buff));//將括號(hào)右邊數(shù)字右邊部分復(fù)制;strcpy(buff, pParenthesesRight + Len + 1);//清除括號(hào)右邊;memset(pParenthesesRight + 1, 0, pSubs->UsedName + strlen(pSubs->UsedName) - (pParenthesesRight + 1));//加上buff(實(shí)際是去了數(shù)字部分);strcat(pSubs->UsedName, buff);/*-----------------------------------------------------*/p = pParenthesesLeft + 1;//遍歷括號(hào)內(nèi),將數(shù)字乘上括號(hào)后的數(shù)字;while (p < pParenthesesRight){if (*p >= '0'&&*p <= '9'){char szNewNum[128] = { 0 };int nNow, lenNow, nNew, lenNew;//變化的長(zhǎng)度;int dtLen;//獲取當(dāng)前數(shù)字和長(zhǎng)度;lenNow = StrToNum(p, &nNow);//計(jì)算新的數(shù)字;nNew = Value*nNow;//將新的數(shù)字轉(zhuǎn)為字符串,保存長(zhǎng)度;lenNew = NumToStr(szNewNum, nNew);//計(jì)算變化的長(zhǎng)度;dtLen = lenNew - lenNow;memset(buff, 0, sizeof(buff));//將當(dāng)前數(shù)字右邊復(fù)制到buff;strcpy(buff, p + lenNow);//將數(shù)字和右面置為0;memset(p, 0, pSubs->UsedName + strlen(pSubs->UsedName) - p);//加上新長(zhǎng)度;strcat(pSubs->UsedName, szNewNum);//加上buff;strcat(pSubs->UsedName, buff);//右括號(hào)向右移動(dòng)dtLen長(zhǎng)度;pParenthesesRight += dtLen;//p移動(dòng)到新數(shù)字后面;p += lenNew;}elsep++;}}//去掉兩邊括號(hào);memset(buff, 0, sizeof(buff));strcpy(buff, pParenthesesRight + 1);memset(pParenthesesRight, 0, pSubs->UsedName + strlen(pSubs->UsedName) - pParenthesesRight);strcat(pSubs->UsedName, buff);/*--------------------------------------------------------------------------------------------*/memset(buff, 0, sizeof(buff));strcpy(buff, pParenthesesLeft + 1);memset(pParenthesesLeft, 0, pSubs->UsedName + strlen(pSubs->UsedName) - pParenthesesLeft);strcat(pSubs->UsedName, buff);}return TRUE; } //分割物質(zhì)組成元素; void DevideElement(SUBSTANCE*pSubs) {char *pEleStart, *pEleEnd;pEleStart = pEleEnd = pSubs->UsedName;while (*pEleStart != NULL){//用數(shù)字分割元素;if (*pEleEnd >= '0'&&*pEleEnd <= '9'){int Value, Len;ELEMENT*pEle;char EleName[64] = { 0 };memcpy(EleName, pEleStart, pEleEnd - pEleStart);pEle = InElementList(EleName, pSubs->elements);if (pEle == NULL){ELEMENT*pEle = NULL;pEle = (ELEMENT*)malloc(sizeof(ELEMENT));pEle->next = pSubs->elements;pSubs->elements = pEle;memset(pEle->Name, 0, sizeof(pEle->Name));memcpy(pEle->Name, pEleStart, pEleEnd - pEleStart);Len = StrToNum(pEleEnd, &pEle->Num);}else{Len = StrToNum(pEleEnd, &Value);pEle->Num += Value;}pEleEnd += Len;pEleStart = pEleEnd;}elsepEleEnd++;} } //檢測(cè)左右元素種類是否守恒; BOOL IsCovered() {//將方程式左邊的元素添加到AllEleClaslist中;SUBSTANCE*pSubs;int RightEleClasCount = 0;ELEMENT*pEle;for (pSubs = LeftSubsHead; pSubs != NULL; pSubs = pSubs->next){for (pEle = pSubs->elements; pEle != NULL; pEle = pEle->next){if (NULL == InElementList(pEle->Name, AllEleCLas)){ELEMENT*pNewEle = (ELEMENT*)malloc(sizeof(ELEMENT));memset(pNewEle, 0, sizeof(ELEMENT));strcpy(pNewEle->Name, pEle->Name);pNewEle->Num = 1;pNewEle->next = AllEleCLas;AllEleCLas = pNewEle;AllEleClasCount++;}}}//與方程式右邊的元素比較;for (pSubs = RightSubsHead; pSubs != NULL; pSubs = pSubs->next){for (pEle = pSubs->elements; pEle != NULL; pEle = pEle->next){ELEMENT*ele = InElementList(pEle->Name, AllEleCLas);if (NULL == ele){strcpy(szRetEquation, "ERROR:方程式左右兩邊元素種類不相同!");return FALSE;}elseele->Num++;}}for (pEle = AllEleCLas; pEle != NULL; pEle = pEle->next){if (pEle->Num == 1){strcpy(szRetEquation, "ERROR:方程式左右兩邊元素種類不相同!");return FALSE;}}return TRUE; } //處理每一種物質(zhì); BOOL BeginProcessStr() {SUBSTANCEPOINTER*pSubsAddr;for (pSubsAddr = AllSubsAddrsHead; pSubsAddr != NULL; pSubsAddr = pSubsAddr->next){//將點(diǎn)轉(zhuǎn)換為括號(hào);CallChangePoint(pSubsAddr->pAddress);//在個(gè)數(shù)為1的元素后面加'1'CallUpdateSubsName(pSubsAddr->pAddress);//去除物質(zhì)中的括號(hào);if (!RemoveParentheses(pSubsAddr->pAddress)){strcpy(szRetEquation, "ERROR:括號(hào)不匹配!");return FALSE;}//分割物質(zhì)組成元素;DevideElement(pSubsAddr->pAddress);}return TRUE; } //生成方程組; void MakeEquationSet() {char buff[128] = { 0 };ELEMENT*pCurEle;for (pCurEle = AllEleCLas; pCurEle != NULL; pCurEle = pCurEle->next){SUBSTANCEPOINTER*pSubsAddr;for (pSubsAddr = AllSubsAddrsHead; pSubsAddr != NULL; pSubsAddr = pSubsAddr->next){ELEMENT*pEle;//這種物質(zhì)是方程右邊的第一種物質(zhì);if (pSubsAddr->pAddress == RightSubsHead && strlen(szEquationSet) != 0){strcpy(szEquationSet + strlen(szEquationSet) - 1, "==");}for (pEle = pSubsAddr->pAddress->elements; pEle != NULL; pEle = pEle->next){if (!strcmp(pCurEle->Name, pEle->Name)){sprintf(buff, "%d%s+", pEle->Num, pSubsAddr->pAddress->kName);strcat(szEquationSet, buff);}}//這種物質(zhì)是方程中最后一種物質(zhì);if (pSubsAddr == AllSubsAddrsTail && strlen(szEquationSet) != 0){strcpy(szEquationSet + strlen(szEquationSet) - 1, ";");}}} } //釋放內(nèi)存; void FreeMemory() {SUBSTANCEPOINTER*pSubsAddr;for (pSubsAddr = AllSubsAddrsHead; pSubsAddr != NULL;){SUBSTANCEPOINTER*tp;ELEMENT*pEle;for (pEle = pSubsAddr->pAddress->elements; pEle != NULL;){ELEMENT *tp = pEle;pEle = pEle->next;free(tp);}free(pSubsAddr->pAddress);tp = pSubsAddr;pSubsAddr = pSubsAddr->next;free(tp);} } //顯示處理過(guò)程; void ShowProcess() {SUBSTANCEPOINTER*pSubsAddr;for (pSubsAddr = AllSubsAddrsHead; pSubsAddr != NULL; pSubsAddr = pSubsAddr->next){ELEMENT*pEle;if (pSubsAddr->pAddress == LeftSubsHead)printf("-----------------------------Left----------------------------\n\n");else if (pSubsAddr->pAddress == RightSubsHead)printf("\n----------------------------Right----------------------------\n\n");printf("::K:%s\tName:%s\tUsedName:%s\n", pSubsAddr->pAddress->kName, pSubsAddr->pAddress->Name, pSubsAddr->pAddress->UsedName);printf("---------------------------elements--------------------------\n");for (pEle = pSubsAddr->pAddress->elements; pEle != NULL; pEle = pEle->next){printf("::::element:%s\tnum:%d\n", pEle->Name, pEle->Num);}printf("-------------------------------------------------------------\n");}printf("-------------------------EquationSet-------------------------\n");printf(szEquationSet);printf("\n-------------------------------------------------------------\n"); } //結(jié)束 void EndChemistryEquationStringProcess() {//釋放內(nèi)存;FreeMemory(); }//處理化學(xué)方程字符串; BOOL ChemistryEquationStringProcess(char*szChemistryEquation) {//清空字符數(shù)組;Init();//--------------------------------------------------------------------------//char szChemistryEquation[] = "Al2(SO4)3+NH3.H2O====Al(OH)3+(NH4)2SO4";strcpy(szEquation, szChemistryEquation);//--------------------------------------------------------------------------//分割方程式,失敗反回FALSE,成功返回TRUE;if (!DevideEquation())return FALSE;//分割各種物質(zhì);if (!DevideSubstance())return FALSE;//處理每一種物質(zhì);if (!BeginProcessStr())return FALSE;//檢測(cè)左右元素種類是否守恒;if (!IsCovered()){strcat(szRetEquation,"元素種類不守恒!");return FALSE;}//生成方程組;MakeEquationSet();//顯示處理過(guò)程;ShowProcess();return TRUE; }EquationSetSolve.h文件:
#pragma once #include <stdio.h> #include <memory.h> #include <stdlib.h> #include <string.h> #include <math.h> #define TYPE_UNKNOWN 1 #define TYPE_CONSTANT 0 #define SUCCESS 0 #define NEXT 1 #define FAIL -1 typedef int BOOL; typedef unsigned int UINT; #define TRUE 1 #define FALSE 0 //分?jǐn)?shù)類型; typedef struct _NUM {int Molecule; //分子;UINT Denominator; //分母,都為正; }NUM; typedef struct _Item {int nType; //是否為未知項(xiàng);char szName[32]; //名稱;NUM k; //系數(shù);struct _Item* next; }Item; typedef struct _Equation {Item*FirstItem; //儲(chǔ)存各個(gè)項(xiàng);struct _Equation* next; }Equation; typedef struct _EquationSet {Equation* FirstEquation; //儲(chǔ)存方程式;struct _EquationSet* next; }EquationSet; //保存結(jié)果; typedef struct _Unknown {char Name[32];NUM value;struct _Unknown*next; }Unknown; //儲(chǔ)存輸入的方程式; typedef struct _EquationString {char szEquation[256];char szEquationLeft[128];char szEquationRight[128];struct _EquationString* next; }EquationString; //儲(chǔ)存多組解; typedef struct _Ret {Unknown*unknown;struct _Ret*next; }Ret; EquationSet *EquationSetHead = NULL; //儲(chǔ)存方程組的結(jié)構(gòu); EquationString * EquationStrHead = NULL; //儲(chǔ)存輸入的方程組字符串; Unknown *AllUnknown = NULL; //儲(chǔ)存所有元的名稱; int UnknownCount = 0; //記錄元的個(gè)數(shù); Unknown *Definite = NULL; //確定的元; Unknown *Varied = NULL; //主動(dòng)變化的元; Unknown *_Varied = NULL; //被動(dòng)變化的元; Ret *RetSolution = NULL; //結(jié)果鏈表首地址; int MaxSolution = 1; //最多求出幾組解; int CurSoluton = 0; //已經(jīng)求出的解的組數(shù); int MaxValue = 3; //主動(dòng)變化元最大值; #define IsInAllUnknown(name) InUnknownList(AllUnknown,name) #define IsDefinite(name) InUnknownList(Definite,name) #define IsVaried(name) InUnknownList(Varied,name) #define Is_Varied(name) InUnknownList(_Varied,name) //統(tǒng)計(jì)確定元的個(gè)數(shù); int GetDefiniteNum() {int n = 0;Unknown*uk;for (uk = Definite; uk != NULL; uk = uk->next)n++;return n; } //是否在unknownlist中; Unknown* InUnknownList(Unknown*List, char *Name) {Unknown *uk;for (uk = List; uk != NULL; uk = uk->next){if (!strcmp(uk->Name, Name))return uk;} return NULL; } //將字符串起始部分的數(shù)字字符轉(zhuǎn)為整數(shù),返回長(zhǎng)度; int StrToNum(char *str, int *n) {char *p = str;int len = 0,i;*n = 0;while (*p >= '0'&&*p <= '9'){p++;len++;}p = str;for (i = 0; i < len; i++, p++){*n += (int)(*p - '0')*pow(10.0, len - 1 - i);}return len; } //將整數(shù)轉(zhuǎn)為字符串,返回長(zhǎng)度; int NumToStr(char *buff, int n) {sprintf(buff, "%d", n);return strlen(buff); } //釋放Unknownlist; void DelUnknownList(Unknown*UkListHead) {Unknown*TempUnknown, *pUk = UkListHead;while (pUk != NULL){TempUnknown = pUk;pUk = pUk->next;free(TempUnknown);} } //釋放Item; #define DelItem(pItem) free(pItem) //釋放方程; void DelEquation(Equation*eqt) {Item*TempItem,*pItem = eqt->FirstItem;while (pItem != NULL){TempItem = pItem;pItem = pItem->next;DelItem(TempItem);}free(eqt); } //釋放方程組; void DelEquationSet(EquationSet*EqtSet) {Equation*TempEqt, *pEqt = EqtSet->FirstEquation;while (pEqt != NULL){TempEqt = pEqt;pEqt = pEqt->next;DelEquation(TempEqt);}free(EqtSet); } //釋放方程組的集合; void DelEquationSetSet(EquationSet*EquationSetListHead) {EquationSet*TempEqtSet, *pEqtSet = EquationSetListHead;while (pEqtSet != NULL){TempEqtSet = pEqtSet;pEqtSet = pEqtSet->next;DelEquationSet(TempEqtSet);} } //釋放儲(chǔ)存的方程字符串; void DelEquationStr() {EquationString*EqtStr = EquationStrHead,*Temp;while(EqtStr){Temp=EqtStr;EqtStr = EqtStr->next;free(Temp);} } //取字符串中的分子分母和元,存到Item中; BOOL GetStrItem(char *str, Item*pItem) {char *p = str;int StrLen = strlen(str),Sign;int Molecule, Denominator,MoleculeLen, DenominatorLen;if (StrLen == 0) //長(zhǎng)度為0無(wú)效,返回false;return FALSE;Sign = 1;if (*p == '-')Sign = -1;p++;if (*p < '0' || *p > '9') //第一個(gè)字符(除了正負(fù)號(hào))不是數(shù)字,將整個(gè)字符串當(dāng)作元名稱;{pItem->nType = TYPE_UNKNOWN;strcpy(pItem->szName, p);pItem->k.Molecule = 1, pItem->k.Denominator = 1; //分子分母都為1;goto success;}//----------------------------------------------------------------------//儲(chǔ)存分子;MoleculeLen = StrToNum(p, &Molecule);if (*(p + MoleculeLen) == NULL) //只有一個(gè)數(shù)是常數(shù)項(xiàng);{pItem->nType = TYPE_CONSTANT;pItem->k.Molecule = Molecule, pItem->k.Denominator = 1;goto success;}if (*(p + MoleculeLen) == '/' && (*(p + MoleculeLen + 1) >= '0' && *(p + MoleculeLen + 1) <= '9')) //找到分?jǐn)?shù)線且分?jǐn)?shù)線后是一個(gè)數(shù);{DenominatorLen = StrToNum(p + MoleculeLen + 1, &Denominator);if ((DenominatorLen + MoleculeLen + 2/*分?jǐn)?shù)線和第一個(gè)正負(fù)號(hào)*/) == StrLen) //只有分?jǐn)?shù);{pItem->nType = TYPE_CONSTANT;}else //是分?jǐn)?shù)和一個(gè)元;{pItem->nType = TYPE_UNKNOWN;strcpy(pItem->szName, p + MoleculeLen + DenominatorLen + 1);}pItem->k.Molecule = Molecule, pItem->k.Denominator = Denominator;if (pItem->k.Denominator == 0) //分母為0,無(wú)效;return FALSE;goto success;}else //一個(gè)整數(shù)加元;{pItem->nType = TYPE_UNKNOWN;strcpy(pItem->szName, p + MoleculeLen);pItem->k.Denominator = 1, pItem->k.Molecule = Molecule;goto success;} success:pItem->k.Molecule *= Sign;return TRUE; } //取絕對(duì)值; UINT ABS(int n) {return n > 0 ? n : -n; } //取最大公因數(shù); UINT GetMaxCommonFactor(int a, int b) {int r = 0;a = ABS(a), b = ABS(b);if (a == 0 || b == 0)return 1;do{if (a < b) a = a^b, b = a^b, a = a^b;r = a%b;a = b, b = r;} while (r);return a; } //取最小公倍數(shù); UINT GetMinCommonMultiple(int a, int b) {a = ABS(a), b = ABS(b);return a*b / GetMaxCommonFactor(a, b); } //在一個(gè)unknownlist中創(chuàng)建一項(xiàng); Unknown*CreateUnknownInUkList(Unknown**UkListHead) {Unknown*pNew = (Unknown*)malloc(sizeof(Unknown));memset(pNew, 0, sizeof(Unknown));pNew->next = (*UkListHead);(*UkListHead) = pNew;return pNew; } //在一個(gè)方程組鏈表中創(chuàng)建一個(gè)方程組; EquationSet * CreateEquationSetInEqtSetList(EquationSet**EqtSetListHead) {//頭插法;EquationSet* pEqtSet = (EquationSet*)malloc(sizeof(EquationSet));pEqtSet->next = (*EqtSetListHead);(*EqtSetListHead) = pEqtSet;(*EqtSetListHead)->FirstEquation = NULL;return pEqtSet; } //在一個(gè)方程組中創(chuàng)建一個(gè)方程; Equation *CreateEquationInEqtSet(EquationSet*EqtSet) {//頭插法;Equation *pEqt = (Equation*)malloc(sizeof(Equation));pEqt->FirstItem = NULL;pEqt->next = EqtSet->FirstEquation;EqtSet->FirstEquation = pEqt;return pEqt; } //在一個(gè)方程組創(chuàng)建一個(gè)項(xiàng); Item* CreateItemInEqt(Equation*Eqt) {//頭插法;Item *pItem = (Item*)malloc(sizeof(Item));memset(pItem, 0, sizeof(Item));pItem->next = Eqt->FirstItem;Eqt->FirstItem = pItem;return pItem; } //用';'分割方程組; BOOL DevideEquationSet(char*szEquation) {char *pStart, *pEnd;char *DevideSign;pStart = pEnd = szEquation;while (1){if (*pStart == NULL){break;}if (*pEnd == ';' || *pEnd == NULL){EquationString*Eqt = (EquationString*)malloc(sizeof(EquationString));Eqt->next = EquationStrHead;EquationStrHead = Eqt;//將整個(gè)方程存到->szEquation中;memset(EquationStrHead->szEquation, 0, sizeof(EquationStrHead->szEquation));memcpy(EquationStrHead->szEquation, pStart, pEnd - pStart);memset(EquationStrHead->szEquationLeft, 0, sizeof(EquationStrHead->szEquationLeft));memset(EquationStrHead->szEquationRight, 0, sizeof(EquationStrHead->szEquationRight));EquationStrHead->szEquationLeft[0] = '+';EquationStrHead->szEquationRight[0] = '+';//----------------------------------------------------------------------------------//分割方程左右兩部份;//找到等于號(hào);DevideSign = EquationStrHead->szEquation;//等號(hào)左邊沒(méi)有東西;if (*DevideSign == '=') return FALSE;while (*DevideSign != '='&&*DevideSign != NULL) DevideSign++;//沒(méi)有等于號(hào);if (*DevideSign == NULL) return FALSE;//儲(chǔ)存左邊;memcpy(EquationStrHead->szEquationLeft+1, EquationStrHead->szEquation, DevideSign - EquationStrHead->szEquation);while (*DevideSign == '=' && *DevideSign != NULL) DevideSign++;// 等號(hào)右邊沒(méi)有東西;if (*DevideSign == NULL) return FALSE;strcpy(EquationStrHead->szEquationRight+1, DevideSign);//----------------------------------------------------------------------------------if (*pEnd != NULL)pEnd++;pStart = pEnd;}else{pEnd++;}}return TRUE; } //設(shè)置起始方程組; BOOL SetStartEquationSet() {char buff[256];Item*pItem;EquationSet*EqtSet = CreateEquationSetInEqtSetList(&EquationSetHead);EquationString*EqtStr;for (EqtStr = EquationStrHead; EqtStr != NULL; EqtStr = EqtStr->next){Equation *NewEquation = CreateEquationInEqtSet(EqtSet);char *pStart,*pEnd;int i;for (i = 0; i < 2; i++){//第一次分割左部分,第二次分割右部分;if (i == 0)pStart = EqtStr->szEquationLeft;elsepStart = EqtStr->szEquationRight;pEnd = pStart + 1;while (1){if (*pStart == NULL)break;if (*pEnd == '+' ||*pEnd=='-' ||*pEnd == NULL){memset(buff, 0, sizeof(buff));memcpy(buff, pStart, pEnd - pStart);pItem = CreateItemInEqt(NewEquation);if (!GetStrItem(buff, pItem))return FALSE; //無(wú)效的項(xiàng);//第一次出現(xiàn)的元,在allunknownlist中添加;if (pItem->nType == TYPE_UNKNOWN && !IsInAllUnknown(pItem->szName)){Unknown*pUk = CreateUnknownInUkList(&AllUnknown);UnknownCount++;strcpy(pUk->Name, pItem->szName);}//分割右邊的項(xiàng)每個(gè)系數(shù)乘-1;if (i == 1)pItem->k.Molecule *= -1;pStart = pEnd;if (pEnd != NULL)pEnd++;}else{pEnd++;}}}}return TRUE; } //化簡(jiǎn)每一項(xiàng)(約分); void SimplyItem(Item*pItem) {int MaxCommonFactor = GetMaxCommonFactor(pItem->k.Molecule, pItem->k.Denominator);pItem->k.Molecule /= MaxCommonFactor;pItem->k.Denominator /= MaxCommonFactor; } //是否為同類項(xiàng); BOOL IsSameClassItem(Item*pItem1, Item*pItem2) {return ((pItem1->nType == pItem2->nType) && !strcmp(pItem1->szName, pItem2->szName)); } //合并兩項(xiàng)儲(chǔ)存到第一項(xiàng)中; void MergeItem(Item*pItem1, Item*pItem2) {//計(jì)算分母的最小公倍數(shù);int MinCommonMutiple = GetMinCommonMultiple(pItem1->k.Denominator, pItem2->k.Denominator);//通分;pItem1->k.Molecule *= MinCommonMutiple / pItem1->k.Denominator;pItem2->k.Molecule *= MinCommonMutiple / pItem2->k.Denominator;pItem1->k.Denominator = pItem2->k.Denominator = MinCommonMutiple;//分子相加;pItem1->k.Molecule += pItem2->k.Molecule; } //化簡(jiǎn)方程式; void SimplyEquation(Equation*eqt) {int MaxCommonFactor = 0;//-----------------------------------合并同類項(xiàng)----------------------------;Item*pItem1,*pItem2,*front,*pItem;for (pItem1 = eqt->FirstItem; pItem1 != NULL;pItem1=pItem1->next){for (pItem2 = pItem1->next, front = pItem1; pItem2 != NULL;){if (IsSameClassItem(pItem1,pItem2)){MergeItem(pItem1, pItem2);front->next = pItem2->next;DelItem(pItem2);pItem2 = front->next;}else{front = front->next;pItem2 = pItem2->next;}}}//-------------------------------------清除系數(shù)為0的項(xiàng)---------------------------;for (pItem = eqt->FirstItem,front=NULL; pItem != NULL; ){if (0 == pItem->k.Molecule){if (front == NULL){eqt->FirstItem = pItem->next;DelItem(pItem);pItem = eqt->FirstItem;}else{front->next = pItem->next;DelItem(pItem);pItem = front->next;}}else{if (front == NULL)front = eqt->FirstItem;elsefront = front->next;pItem = front->next;}}//每一項(xiàng)約分;for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next){SimplyItem(pItem);}//獲取所有項(xiàng)的最大公因數(shù);for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next){if (MaxCommonFactor == 0)MaxCommonFactor = pItem->k.Molecule;elseMaxCommonFactor = GetMaxCommonFactor(MaxCommonFactor, pItem->k.Molecule);}//每一項(xiàng)同除以最大公因數(shù);if (MaxCommonFactor != 1){for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next){pItem->k.Molecule /= MaxCommonFactor;}} } //獲取常數(shù)項(xiàng)或元個(gè)數(shù); int GetConstOrUnknownNum(Equation*Eqt,int nType) {int n=0;Item*pItem;for(pItem = Eqt->FirstItem;pItem!=NULL;pItem=pItem->next){if(pItem->nType == nType)n++;}return n; } //方程中是否存在某一個(gè)元; Item* EqtExistItem(Equation *eqt,int nType,char *szUnknownName) {Item*pItem;for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next){if ((nType == pItem->nType) && !strcmp(pItem->szName, szUnknownName))break;}return pItem; } 獲取方程組出現(xiàn)次數(shù)最少的元,儲(chǔ)存到Name中; void GetLeastUnknown(EquationSet*EqtSet, char*Name,int size) {Unknown *UnknInfo = NULL,*LeastUnknown = NULL,*pFindUnk = NULL,*pNewUnkn = NULL,*pUnknInfo = NULL;Equation*eqt;Item*pItem;//把所有的元儲(chǔ)存到鏈表中并記錄出現(xiàn)的次數(shù);for (eqt = EqtSet->FirstEquation; eqt != NULL; eqt = eqt->next){for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next){if (pItem->nType == TYPE_UNKNOWN){//查找是否存在;pFindUnk = InUnknownList(UnknInfo,pItem->szName);//不存在,加到鏈表中;if (pFindUnk == NULL){pNewUnkn = CreateUnknownInUkList(&UnknInfo);pNewUnkn->value.Molecule = 1;strcpy(pNewUnkn->Name, pItem->szName);}else{pFindUnk->value.Molecule++;}}}}for (pUnknInfo = UnknInfo; pUnknInfo != NULL; pUnknInfo = pUnknInfo->next){//如果是第一個(gè)且出現(xiàn)次數(shù)大于1;if (LeastUnknown == NULL && pUnknInfo->value.Molecule > 1)LeastUnknown = pUnknInfo;//否則,如果小于leastUnknown則設(shè)置LeastUnknown==pUnknInfo;else if (pUnknInfo->value.Molecule > 1 && pUnknInfo->value.Molecule<LeastUnknown->value.Molecule)LeastUnknown = pUnknInfo;}memset(Name, 0, size);if (LeastUnknown != NULL)//每個(gè)元只出現(xiàn)了一次為空;strcpy(Name, LeastUnknown->Name);//釋放內(nèi)存;DelUnknownList(UnknInfo); } //化解每個(gè)方程并刪除方程組中的空方程; void SimplyEquationSet(EquationSet*EqtSet) {Equation*Eqt = NULL,*front = NULL;//刪除空方程;for(Eqt = EqtSet->FirstEquation,front = NULL;Eqt!=NULL;){SimplyEquation(Eqt);//空方程刪除;if(Eqt->FirstItem==NULL){if(front==NULL){EqtSet->FirstEquation=Eqt->next;DelEquation(Eqt);Eqt = EqtSet->FirstEquation;}else{front->next=Eqt->next;DelEquation(Eqt);Eqt=front->next;}}else{if(front == NULL)front=EqtSet->FirstEquation;elsefront=front->next;Eqt=front->next;}} } //兩個(gè)方程消元,反回新的方程; Equation* ClearEquationUnknown(Equation*eqt1, Equation*eqt2,Item*pItem1,Item*pItem2) {Item*pItem,*NewItem,*FindItem;Equation*NewEquation;int DenoMinCommonMultiple,MoleMinCommonMultiple,Eqt1Multiply,Eqt2Multiply;//記錄兩個(gè)方程相加還是相減;BOOL bChangeSign;bChangeSign = (pItem1->k.Molecule*pItem2->k.Molecule)>=0;//取分母最小公倍數(shù);DenoMinCommonMultiple = GetMinCommonMultiple(pItem1->k.Denominator, pItem2->k.Denominator);pItem1->k.Molecule*= DenoMinCommonMultiple / pItem1->k.Denominator;pItem2->k.Molecule *= DenoMinCommonMultiple / pItem2->k.Denominator;pItem1->k.Denominator= pItem2->k.Denominator = DenoMinCommonMultiple;//取分子最小公倍數(shù);MoleMinCommonMultiple = GetMinCommonMultiple(pItem1->k.Molecule, pItem2->k.Molecule);//計(jì)算第一個(gè)方程每一項(xiàng)要乘的數(shù);Eqt1Multiply = MoleMinCommonMultiple / ABS(pItem1->k.Molecule);//計(jì)算第一個(gè)方程每一項(xiàng)要乘的數(shù);Eqt2Multiply = MoleMinCommonMultiple / ABS(pItem2->k.Molecule);//給第一個(gè)方程的每一項(xiàng)乘上Eqt1Multiply;for (pItem = eqt1->FirstItem; pItem != NULL; pItem = pItem->next){pItem->k.Molecule*=Eqt1Multiply;}//給第一個(gè)方程的每一項(xiàng)乘上Eqt1Multiply;for (pItem = eqt2->FirstItem; pItem != NULL; pItem = pItem->next){pItem->k.Molecule*=Eqt2Multiply;//如果同號(hào),將方程2所有的符號(hào)取反;if (bChangeSign){pItem->k.Molecule*=-1;}}//儲(chǔ)存生成的新方程;NewEquation = (Equation*)malloc(sizeof(Equation));memset(NewEquation,0,sizeof(Equation));//先把eqt1復(fù)制到NewEquation中;for (pItem = eqt1->FirstItem; pItem != NULL; pItem = pItem->next){NewItem = CreateItemInEqt(NewEquation);memcpy(NewItem, pItem, sizeof(Item)-4/*減去四個(gè)字節(jié)(next指針)*/);}//遍歷eqt2各個(gè)項(xiàng),在NewEquation中查找是否存在,不存在添加,存在合并;for (pItem = eqt2->FirstItem; pItem != NULL; pItem = pItem->next){FindItem = EqtExistItem(NewEquation, pItem->nType, pItem->szName);if (FindItem == NULL) //不存在;{//在NewEquation中添加該項(xiàng)Item*NewItem = CreateItemInEqt(NewEquation);memcpy(NewItem, pItem, sizeof(Item)-4/*減去四個(gè)字節(jié)(next指針)*/);}else //存在該項(xiàng);MergeItem(FindItem, pItem);}SimplyEquation(eqt1);SimplyEquation(eqt2);SimplyEquation(NewEquation);return NewEquation; } //方程組開(kāi)始消元; void BeginEliminationUnknown() {char LeastUnknown[32] = { 0 };while(1){int EqtSetExist = 0;Equation*eqt1,*eqt2,*front;EquationSet*EqtSet = EquationSetHead;SimplyEquationSet(EqtSet);//找出出現(xiàn)次數(shù)最少的元;GetLeastUnknown(EqtSet, LeastUnknown, sizeof(LeastUnknown));//不存在出現(xiàn)次數(shù)最少的元;if (*LeastUnknown == '\0')break;for (eqt1 = EqtSet->FirstEquation, front = NULL; eqt1 != NULL;){Item*FindItem1 = EqtExistItem(eqt1, TYPE_UNKNOWN, LeastUnknown);Item*FindItem2;//標(biāo)記只創(chuàng)建一個(gè)下一個(gè)方程組;//如果不存在最少次數(shù)元,把這個(gè)方程放到下一個(gè)方程組;if (FindItem1 == NULL){if(EqtSetExist==0){CreateEquationSetInEqtSetList(&EquationSetHead);EqtSetExist=1;}//移動(dòng)這個(gè)方程,下一個(gè)方程組是EquationSetHead;if (front == NULL){EqtSet->FirstEquation = eqt1->next;eqt1->next = EquationSetHead->FirstEquation;EquationSetHead->FirstEquation= eqt1;eqt1 = EqtSet->FirstEquation;}else{front->next = eqt1->next;eqt1->next = EquationSetHead->FirstEquation;EquationSetHead->FirstEquation= eqt1;eqt1 = front->next;}}else //如果這個(gè)方程存在出現(xiàn)最少次數(shù)元,則從下一個(gè)方程開(kāi)始尋找;{for (eqt2 = eqt1->next; eqt2 != NULL; eqt2 = eqt2->next){FindItem2 = EqtExistItem(eqt2, TYPE_UNKNOWN, LeastUnknown);if (FindItem2 != NULL){Equation*NewEquation = ClearEquationUnknown(eqt1,eqt2,FindItem1,FindItem2);//不存在下一個(gè)方程組添加;if (EqtSetExist==0){CreateEquationSetInEqtSetList(&EquationSetHead);EqtSetExist=1;}NewEquation->next = EquationSetHead->FirstEquation;EquationSetHead->FirstEquation = NewEquation;}}if (front == NULL)front = EqtSet->FirstEquation;elsefront = front->next;eqt1 = front->next;}}} } //將方程組中的方程按未知項(xiàng)個(gè)數(shù)排序; void SortEquation(EquationSet*EqtSet) {//記錄方程個(gè)數(shù);int EquationNum = 0;int i,j;Equation*Eqt;for(Eqt = EqtSet->FirstEquation;Eqt!=NULL;Eqt=Eqt->next)EquationNum++;for (i = 0; i < EquationNum - 1; i++){Equation*CurEqt = EqtSet->FirstEquation, *front = NULL;for (j = 0; j < EquationNum-1-i; j++){//如果當(dāng)前的方程式未知項(xiàng)項(xiàng)數(shù)多于下一項(xiàng),交換位置;if (GetConstOrUnknownNum(CurEqt,TYPE_UNKNOWN)>GetConstOrUnknownNum(CurEqt->next,TYPE_UNKNOWN)){if (front == NULL){EqtSet->FirstEquation = CurEqt->next;front = EqtSet->FirstEquation;CurEqt->next = CurEqt->next->next;front->next = CurEqt;}else{front->next = CurEqt->next;CurEqt->next = CurEqt->next->next;front->next->next = CurEqt;front = front->next;}}else{if (front == NULL)front = EqtSet->FirstEquation;elsefront = front->next;CurEqt = front->next;}}} } //從EqtSet最后一組起設(shè)置確定量和變化量 BOOL SetDefinite(EquationSet*EqtSetHead) {EquationSet*CurEqtSet;for (CurEqtSet = EqtSetHead; CurEqtSet != NULL; CurEqtSet = CurEqtSet->next){Equation*eqt;SimplyEquationSet(CurEqtSet);//按項(xiàng)數(shù)多少排序;SortEquation(CurEqtSet);for (eqt = CurEqtSet->FirstEquation; eqt != NULL; eqt = eqt->next){//查找元的值是否確定,將確定的值帶入其中;Unknown* FindUnknown = NULL;Item*pItem;int UnknownNum,ConstNum,_VariedSet = 0;;for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next){if (pItem->nType == TYPE_UNKNOWN){FindUnknown = IsDefinite(pItem->szName);//值已經(jīng)確定;if (FindUnknown != NULL){//設(shè)為常數(shù)項(xiàng);pItem->nType = TYPE_CONSTANT;memset(pItem->szName, 0, sizeof(pItem->szName));//分子相乘,分母相乘;pItem->k.Molecule*= FindUnknown->value.Molecule;pItem->k.Denominator*=FindUnknown->value.Denominator;}}}//化簡(jiǎn)一次;SimplyEquation(eqt);UnknownNum = GetConstOrUnknownNum(eqt,TYPE_UNKNOWN);ConstNum = GetConstOrUnknownNum(eqt,TYPE_CONSTANT);//所有項(xiàng)都消完;if (UnknownNum == 0 && ConstNum == 0)continue;//左邊沒(méi)有未知項(xiàng),只有常數(shù)項(xiàng)且不等于0;if (UnknownNum == 0 && ConstNum != 0)return FALSE;//只有一個(gè)未知項(xiàng),可以確定值;if (UnknownNum == 1){Item*pUnknownItem,*pConstItem;Unknown*pNew;if (eqt->FirstItem->nType == TYPE_UNKNOWN){ pUnknownItem = eqt->FirstItem;pConstItem = pUnknownItem->next;}else{pConstItem = eqt->FirstItem;pUnknownItem = pConstItem->next;}//如果是被動(dòng)變化量,尾插法;if (Is_Varied(pUnknownItem->szName)){Unknown*pTail = Definite;while (pTail != NULL && pTail->next != NULL)pTail = pTail->next;pNew = (Unknown*)malloc(sizeof(Unknown));if (pTail == NULL)Definite = pNew;elsepTail->next = pNew;memset(pNew,0,sizeof(Unknown));}else//頭插法;pNew = CreateUnknownInUkList(&Definite);pNew->value.Molecule=pNew->value.Denominator=1;//復(fù)制名稱;strcpy(pNew->Name, pUnknownItem->szName);if (pConstItem == 0) //元的值為0;pNew->value.Molecule=0;else //元的值不為0;{pNew->value.Molecule = ABS(pUnknownItem->k.Denominator)*ABS(pConstItem->k.Molecule);pNew->value.Denominator=ABS(pUnknownItem->k.Molecule)*ABS(pConstItem->k.Denominator);if(pUnknownItem->k.Molecule*pConstItem->k.Molecule>0) //結(jié)果為負(fù);pNew->value.Molecule*=-1;}continue;}//留一個(gè)被動(dòng)變化值的位置;for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next){if (pItem->nType == TYPE_UNKNOWN && !IsVaried(pItem->szName) && !Is_Varied(pItem->szName)){//還沒(méi)有設(shè)置被動(dòng)變化量;if(_VariedSet == 0){//加到被動(dòng)變化量中;Unknown*unk = CreateUnknownInUkList(&_Varied);strcpy(unk->Name, pItem->szName);_VariedSet = 1;}else{//加到主動(dòng)變化量中;Unknown*unk = CreateUnknownInUkList(&Varied);unk->value.Molecule=1;unk->value.Denominator=1;strcpy(unk->Name, pItem->szName);}}}}}return TRUE; } //創(chuàng)建EquationSet的副本 EquationSet* CopyEquationSet() {EquationSet*RetEquationSet = NULL,*NewCurEqtSet = NULL,*EqtSet;for (EqtSet = EquationSetHead; EqtSet != NULL; EqtSet = EqtSet->next){Equation*eqt;//沒(méi)有頭,尾插法;if (NewCurEqtSet == NULL)NewCurEqtSet = RetEquationSet =(EquationSet*)malloc(sizeof(EquationSet));else{NewCurEqtSet->next = (EquationSet*)malloc(sizeof(EquationSet));NewCurEqtSet = NewCurEqtSet->next;}memset(NewCurEqtSet,0,sizeof(EquationSet));for (eqt = EqtSet->FirstEquation; eqt != NULL; eqt = eqt->next){Equation * NewEquation = CreateEquationInEqtSet(NewCurEqtSet);Item*pItem;for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next){Item*NewItem = CreateItemInEqt(NewEquation);memcpy(NewItem, pItem, sizeof(Item)-4);}}}return RetEquationSet; } //保存結(jié)果; void SaveRet() {Unknown *NewUnknown = NULL,*uk;Ret*pRet = (Ret*)malloc(sizeof(Ret));pRet->unknown = NULL;pRet->next = RetSolution;RetSolution = pRet;for (uk = Definite; uk != NULL; uk = uk->next){if (NewUnknown == NULL)NewUnknown = pRet->unknown = (Unknown*)malloc(sizeof(Unknown));else{NewUnknown->next = (Unknown*)malloc(sizeof(Unknown));NewUnknown = NewUnknown->next;}NewUnknown->next = NULL;memcpy(NewUnknown, uk, sizeof(Unknown)-4);} } //當(dāng)存在主動(dòng)變化值時(shí)用枚舉法解出給定個(gè)數(shù)組解; int Solve(Unknown * unknown) {//沒(méi)有主動(dòng)變化量,都是確定的量;if (Varied == NULL)return SUCCESS;//主動(dòng)變化量鏈表尾端,主動(dòng)變化量已經(jīng)設(shè)置好;if (unknown == NULL){EquationSet*TempEquationSet;//已經(jīng)解完,退出;if (CurSoluton >= MaxSolution)return SUCCESS;//創(chuàng)建方程組s的副本;TempEquationSet = CopyEquationSet();if (FALSE == SetDefinite(TempEquationSet)) //無(wú)解,退出;{//刪除方程組s的副本;DelEquationSet(TempEquationSet);return FAIL;}else //保存該組解;{CurSoluton++;SaveRet();//刪除方程組s的副本;DelEquationSet(TempEquationSet);return NEXT;}}else //設(shè)置該主動(dòng)變化量的值;{while (1){int ret;//-----------------------------------------------------------------------------//在Definite中添加該項(xiàng)Unknown*unk = Definite,*_unk,*front;while (unk != NULL && unk->next!=NULL)unk = unk->next;if (unk == NULL)unk = Definite = (Unknown*)malloc(sizeof(Unknown));else{unk->next = (Unknown*)malloc(sizeof(Unknown));unk = unk->next;}memset(unk, 0, sizeof(Unknown));memcpy(unk, unknown, sizeof(Unknown)-4);//-----------------------------------------------------------------------------ret = Solve(unknown->next);//-----------------------------------------------------------------------------//刪除Definite中當(dāng)前元及后面的項(xiàng);for (_unk = Definite,front = NULL; _unk != NULL;){Unknown*__unk;if (strcmp(_unk->Name, unknown->Name) == 0){if (front == NULL)Definite = NULL;elsefront->next = NULL;for (__unk = _unk; __unk != NULL;){Unknown*tp = __unk;__unk = __unk->next;free(tp);}break;}else{front = _unk;_unk = front->next;}}//-----------------------------------------------------------------------------if (ret == FAIL)return FAIL;if (ret == SUCCESS)return SUCCESS;if (ret == NEXT){if (unknown->value.Molecule >= MaxValue){if (unknown == Varied){Unknown*last;MaxValue += 3;//找到最后一個(gè)Varied,值加一;last = Varied;while (last->next != NULL)last = last->next;last->value.Molecule++;}elsereturn NEXT;}elseunknown->value.Molecule++;}}} } //結(jié)束; void EndEquationSetSolve() {Ret*pRet = RetSolution,*temp;while(pRet){DelUnknownList(pRet->unknown);temp = pRet;pRet = pRet->next;free(temp);}DelEquationStr();DelEquationSet(EquationSetHead); } BOOL EquationSetSolve(char*szEquationSet) {EquationSet*EqtSet;//B==2D;5B==3C+8D;2A==1C;3A==1D;12A+B==3C+4D;if(FALSE == DevideEquationSet(szEquationSet))return FALSE;if(FALSE == SetStartEquationSet())return FALSE;//開(kāi)始兩兩消元;BeginEliminationUnknown();if(FALSE == SetDefinite(EquationSetHead))return FALSE;if(GetDefiniteNum() == UnknownCount)return FALSE;if(FAIL == Solve(Varied))return FALSE;return TRUE; }main.c文件:
#include "ChemistryEquationStringProcess.h" #include "EquationSetSolve.h"int main(int argc,char* argv[]) {SUBSTANCEPOINTER*pSubsAddr;char szRet[256] = {0};char buff[32];Unknown*uk;int MinCommonMultiple = 0;if(argc!=2){ printf("%s:Invalid Chemistry Equation!\n",argv[0]);return 0;}if(FALSE == ChemistryEquationStringProcess(argv[1])){printf("Invalid Chemistry Equation!\n");printf("%s\n",szRetEquation);return 0;}if(FALSE == EquationSetSolve(szEquationSet)){printf("Sorry,this chemistry equation doesn't have solution!\n");return 0;}//----------------------取分母最小公倍數(shù)---------------------;for(uk = RetSolution->unknown;uk!=NULL;uk=uk->next){if(MinCommonMultiple == 0)MinCommonMultiple = uk->value.Denominator;elseMinCommonMultiple = GetMinCommonMultiple(uk->value.Denominator,MinCommonMultiple);}//----------------------通分-----------------------------;for(uk = RetSolution->unknown;uk!=NULL;uk=uk->next)uk->value.Molecule*=MinCommonMultiple/uk->value.Denominator;//----------------------------生成結(jié)果--------------------------;strcat(szRet,"\n------------------------result-----------------------\n");for(pSubsAddr = AllSubsAddrsHead;pSubsAddr!=NULL;pSubsAddr=pSubsAddr->next){Unknown*uk;for(uk = RetSolution->unknown;uk!=NULL;uk=uk->next){if(!strcmp(uk->Name,pSubsAddr->pAddress->kName)){if(uk->value.Molecule!=1){sprintf(buff,"%d",uk->value.Molecule);strcat(szRet,buff);}strcat(szRet,pSubsAddr->pAddress->Name);if(pSubsAddr->pAddress->next != NULL && pSubsAddr->next->pAddress != RightSubsHead)strcat(szRet,"+");if(pSubsAddr->next!=NULL &&pSubsAddr->next->pAddress == RightSubsHead)strcat(szRet,"===");}}}strcat(szRet,"\n------------------------result-----------------------\n");//--------------------------輸出結(jié)果--------------------------;printf(szRet);//釋放內(nèi)存;EndChemistryEquationStringProcess();EndEquationSetSolve();return 0; }能力有限,用了2000多行代碼
大神勿噴
總結(jié)
以上是生活随笔為你收集整理的----化学方程式配平工具----的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 小白看完都会了!mysql面试题sql语
- 下一篇: 无形胜有形——0day破解组织探秘