----化学方程式配平工具----

(利用待定化学计量数法配平,先根据每种元素列出方程组,然后解方程组,就可以解出计量数之比)在这里插入图片描述

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 0

typedef struct _ELEMENT
{
	char Name[128];		//元素名称;
	int Num;			//数量;
	struct _ELEMENT *next;
}ELEMENT;

typedef struct _SUBSTANCE
{
	char kName[64];		//给系数设置元;
	char Name[128];		//物质名称;
	char UsedName[128];	//Used Name;
	ELEMENT *elements;	//组成物质的元素;
	struct _SUBSTANCE *next;
}SUBSTANCE;

typedef struct _SUBSTANCEPOINTER
{
	SUBSTANCE*pAddress;
	struct _SUBSTANCEPOINTER*next;
}SUBSTANCEPOINTER;


char kName = 'A';		//每种物质前的元;

SUBSTANCE *LeftSubsHead = 0;	//储存左边的物质;
SUBSTANCE *LeftSubsTail = 0;

SUBSTANCE *RightSubsHead = 0;	//储存右边的物质;
SUBSTANCE *RightSubsTail = 0;	//储存右边的物质;

ELEMENT*AllEleCLas = 0;			//储存所有的元素;
int AllEleClasCount = 0;		//记录元素的个数;

SUBSTANCEPOINTER *AllSubsAddrsHead = NULL;		//记录所有元素的地址;
SUBSTANCEPOINTER *AllSubsAddrsTail = NULL;

char szEquationSet[128];		//储存生成的方程组;
char szEquation[2048];			//储存方程式;
char szRetEquation[2048];		//储存方程式;
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;
}

//清空字符数组;
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;
	//等号左边没有东西;
	if (*p == '=')
		return FALSE;
	while (*p != '='&& *p != NULL) p++;
	//没有等于号;
	if (*p == NULL)
		return FALSE;
	//储存方程式左部分;
	memcpy(szLeftEqua, szEquation, p - szEquation);
	//移到方程式右部分开始处;
	while (*p == '='&& *p != NULL) p++;
	//等号右边没有东西;
	if (*p == NULL)
		return FALSE;
	//储存右边的方程式;
	strcpy(szRightEqua, p);
	//方便后面分割各种物质;
	strcat(szLeftEqua, "+");
	strcat(szRightEqua, "+");
	return TRUE;
}
//分割各种物质;
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;
			/*-----------------------------------------------------------------------------------*/

			//设置新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++;

			//忽略已经填写的系数;
			while (*pSubsStart >= '0' && *pSubsStart <= '9')
				pSubsStart++;
			//常数项,没有元素名称;
			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()
{
	//分割左边的物质;
	if (!CallDevideSubstance(szLeftEqua, &LeftSubsHead, &LeftSubsTail))
		return FALSE;
	//分割右边的物质;
	if (!CallDevideSubstance(szRightEqua, &RightSubsHead, &RightSubsTail))
		return FALSE;
	return TRUE;
}
//将点转换为括号;
void CallChangePoint(SUBSTANCE*pSubs)
{
	char *pPointStart, *pPointEnd;
	int value = 0, len = 0;
	char buff[128] = { 0 };
	while (1)
	{
		pPointEnd = pSubs->UsedName;
		//查找开始点;
		while (*pPointEnd != '.' && *pPointEnd != NULL)
			pPointEnd++;
		pPointStart = pPointEnd;
		//不存在点;
		if (*pPointStart == NULL)
			break;
		pPointEnd++;
		//查找结束点;
		while (*pPointEnd != '.' && *pPointEnd != NULL)
			pPointEnd++;

		//开始转换点;
		//如果点后面为数字;
		if (*(pPointStart + 1) >= '0' && *(pPointStart + 1) <= '9')
		{
			//将结束点后(包括点)复制到buff中;
			memcpy(buff, pPointEnd, pSubs->UsedName + strlen(pSubs->UsedName) - pPointEnd);
			//将结束点后(包括点)置为0
			memset(pPointEnd, 0, pSubs->UsedName + strlen(pSubs->UsedName) - pPointEnd);
			strcat(pSubs->UsedName, ")");
			len = StrToNum(pPointStart + 1, &value);
			//添加数字到后面;
			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);
		}

	}
}
//在个数为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'))
		{
			//当前元素结尾没有数字;
			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);
}
//去除物质中的括号;
BOOL RemoveParentheses(SUBSTANCE*pSubs)
{
	char buff[128];
	char*pParenthesesLeft, *pParenthesesRight;
	while (1)
	{

		pParenthesesLeft = pParenthesesRight = pSubs->UsedName;
		//转移到最内层括号处;
		while (*pParenthesesRight != ')'&&*pParenthesesRight != NULL)
		{
			if (*pParenthesesRight == '(')
				pParenthesesLeft = pParenthesesRight;
			pParenthesesRight++;
		}
		//没有右边括号;
		if (*pParenthesesRight == NULL)
		{
			//但是还有左边括号;
			if (*pParenthesesLeft == '(')
				//不匹配;
				return FALSE;
			//正常,没有括号,退出循环;
			break;
		}
		//找到右括号,但左面无括号,错误;
		if (*pParenthesesLeft != '(')
			return FALSE;
		//括号右边为数字;
		if (*(pParenthesesRight + 1) >= '0'&&*(pParenthesesRight + 1) <= '9')
		{
			char *p;
			int Value, Len;
			Len = StrToNum(pParenthesesRight + 1, &Value);

			memset(buff, 0, sizeof(buff));
			//将括号右边数字右边部分复制;
			strcpy(buff, pParenthesesRight + Len + 1);
			//清除括号右边;
			memset(pParenthesesRight + 1, 0, pSubs->UsedName + strlen(pSubs->UsedName) - (pParenthesesRight + 1));
			//加上buff(实际是去了数字部分);
			strcat(pSubs->UsedName, buff);
			/*-----------------------------------------------------*/
			p = pParenthesesLeft + 1;
			//遍历括号内,将数字乘上括号后的数字;
			while (p < pParenthesesRight)
			{
				if (*p >= '0'&&*p <= '9')
				{
					char szNewNum[128] = { 0 };
					int nNow, lenNow, nNew, lenNew;
					//变化的长度;
					int dtLen;
					//获取当前数字和长度;
					lenNow = StrToNum(p, &nNow);
					//计算新的数字;
					nNew = Value*nNow;
					//将新的数字转为字符串,保存长度;
					lenNew = NumToStr(szNewNum, nNew);
					//计算变化的长度;
					dtLen = lenNew - lenNow;
					memset(buff, 0, sizeof(buff));
					//将当前数字右边复制到buff;
					strcpy(buff, p + lenNow);
					//将数字和右面置为0;
					memset(p, 0, pSubs->UsedName + strlen(pSubs->UsedName) - p);
					//加上新长度;
					strcat(pSubs->UsedName, szNewNum);
					//加上buff;
					strcat(pSubs->UsedName, buff);
					//右括号向右移动dtLen长度;
					pParenthesesRight += dtLen;
					//p移动到新数字后面;
					p += lenNew;
				}
				else
					p++;
			}
		}
		//去掉两边括号;
		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;
}
//分割物质组成元素;
void DevideElement(SUBSTANCE*pSubs)
{
	char *pEleStart, *pEleEnd;
	pEleStart = pEleEnd = pSubs->UsedName;
	while (*pEleStart != NULL)
	{
		//用数字分割元素;
		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;
		}
		else
			pEleEnd++;
	}
}
//检测左右元素种类是否守恒;
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;
			}
			else
				ele->Num++;
		}
	}
	for (pEle = AllEleCLas; pEle != NULL; pEle = pEle->next)
	{
		if (pEle->Num == 1)
		{
			strcpy(szRetEquation, "ERROR:方程式左右两边元素种类不相同!");
			return FALSE;
		}
	}
	return TRUE;
}
//处理每一种物质;
BOOL BeginProcessStr()
{
	SUBSTANCEPOINTER*pSubsAddr;
	for (pSubsAddr = AllSubsAddrsHead; pSubsAddr != NULL; pSubsAddr = pSubsAddr->next)
	{
		//将点转换为括号;
		CallChangePoint(pSubsAddr->pAddress);
		//在个数为1的元素后面加'1'
		CallUpdateSubsName(pSubsAddr->pAddress);
		//去除物质中的括号;
		if (!RemoveParentheses(pSubsAddr->pAddress))
		{
			strcpy(szRetEquation, "ERROR:括号不匹配!");
			return FALSE;
		}
		//分割物质组成元素;
		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;
			//这种物质是方程右边的第一种物质;
			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);
				}
			}
			//这种物质是方程中最后一种物质;
			if (pSubsAddr == AllSubsAddrsTail && strlen(szEquationSet) != 0)
			{
				strcpy(szEquationSet + strlen(szEquationSet) - 1, ";");
			}
		}
	}
}
//释放内存;
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);
	}
}
//显示处理过程;
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");
}
//结束
void EndChemistryEquationStringProcess()
{
	//释放内存;
	FreeMemory();
}

//处理化学方程字符串;
BOOL ChemistryEquationStringProcess(char*szChemistryEquation)
{
	//清空字符数组;
	Init();
	//--------------------------------------------------------------------------
	//char szChemistryEquation[] = "Al2(SO4)3+NH3.H2O====Al(OH)3+(NH4)2SO4";
	strcpy(szEquation, szChemistryEquation);
	//--------------------------------------------------------------------------
	//分割方程式,失败反回FALSE,成功返回TRUE;
	if (!DevideEquation())
		return FALSE;
	//分割各种物质;
	if (!DevideSubstance())
		return FALSE;
	//处理每一种物质;
	if (!BeginProcessStr())
		return FALSE;
	//检测左右元素种类是否守恒;
	if (!IsCovered())
	{
		strcat(szRetEquation,"元素种类不守恒!");
		return FALSE;
	}
	//生成方程组;
	MakeEquationSet();
	//显示处理过程;
	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
//分数类型;
typedef struct _NUM
{
	int Molecule;				//分子;
	UINT Denominator;			//分母,都为正;
}NUM;
typedef struct _Item
{
	int  nType;					//是否为未知项;
	char szName[32];			//名称;
	NUM k;						//系数;
	struct _Item* next;
}Item;
typedef struct _Equation
{
	Item*FirstItem;				//储存各个项;
	struct _Equation* next;
}Equation;
typedef struct _EquationSet
{
	Equation* FirstEquation;	//储存方程式;
	struct _EquationSet* next;
}EquationSet;
//保存结果;
typedef struct _Unknown
{
	char Name[32];
	NUM value;
	struct _Unknown*next;
}Unknown;
//储存输入的方程式;
typedef struct _EquationString
{
	char szEquation[256];
	char szEquationLeft[128];
	char szEquationRight[128];
	struct _EquationString* next;
}EquationString;
//储存多组解;
typedef struct _Ret
{
	Unknown*unknown;
	struct _Ret*next;
}Ret;
EquationSet *EquationSetHead = NULL;				//储存方程组的结构;
EquationString * EquationStrHead = NULL;			//储存输入的方程组字符串;
Unknown *AllUnknown = NULL;							//储存所有元的名称;
int UnknownCount = 0;								//记录元的个数;
Unknown *Definite = NULL;							//确定的元;
Unknown *Varied = NULL;								//主动变化的元;
Unknown *_Varied = NULL;							//被动变化的元;
Ret *RetSolution = NULL;							//结果链表首地址;
int MaxSolution = 1;								//最多求出几组解;
int CurSoluton = 0;									//已经求出的解的组数;
int MaxValue = 3;									//主动变化元最大值;
#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)
//统计确定元的个数;
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;
}
//将字符串起始部分的数字字符转为整数,返回长度;
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;
}
//将整数转为字符串,返回长度;
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);
	}
}
//释放储存的方程字符串;
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)					//长度为0无效,返回false;
		return FALSE;

	Sign = 1;
	if (*p == '-')
		Sign = -1;
	p++;
	if (*p < '0' || *p > '9')																			//第一个字符(除了正负号)不是数字,将整个字符串当作元名称;
	{
		pItem->nType = TYPE_UNKNOWN;
		strcpy(pItem->szName, p);
		pItem->k.Molecule = 1, pItem->k.Denominator = 1;												//分子分母都为1;
		goto success;
	}
	//----------------------------------------------------------------------
	//储存分子;
	MoleculeLen = StrToNum(p, &Molecule);
	if (*(p + MoleculeLen) == NULL)																		//只有一个数是常数项;
	{
		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'))	//找到分数线且分数线后是一个数;
	{
		DenominatorLen = StrToNum(p + MoleculeLen + 1, &Denominator);
		if ((DenominatorLen + MoleculeLen + 2/*分数线和第一个正负号*/) == StrLen)							//只有分数;
		{
			pItem->nType = TYPE_CONSTANT;
		}
		else																							//是分数和一个元;
		{
			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,无效;
			return FALSE;
		goto success;
	}
	else																								//一个整数加元;
	{
		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;
}
//取绝对值;
UINT ABS(int n)
{
	return n > 0 ? n : -n;
}
//取最大公因数;
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;
}
//取最小公倍数;
UINT GetMinCommonMultiple(int a, int b)
{
	a = ABS(a), b = ABS(b);
	return a*b / GetMaxCommonFactor(a, b);
}
//在一个unknownlist中创建一项;
Unknown*CreateUnknownInUkList(Unknown**UkListHead)
{
	Unknown*pNew = (Unknown*)malloc(sizeof(Unknown));
	memset(pNew, 0, sizeof(Unknown));
	pNew->next = (*UkListHead);
	(*UkListHead) = pNew;
	return pNew;
}
//在一个方程组链表中创建一个方程组;
EquationSet * CreateEquationSetInEqtSetList(EquationSet**EqtSetListHead)
{
	//头插法;
	EquationSet* pEqtSet = (EquationSet*)malloc(sizeof(EquationSet));
	pEqtSet->next = (*EqtSetListHead);
	(*EqtSetListHead) = pEqtSet;
	(*EqtSetListHead)->FirstEquation = NULL;
	return pEqtSet;
}
//在一个方程组中创建一个方程;
Equation *CreateEquationInEqtSet(EquationSet*EqtSet)
{
	//头插法;
	Equation *pEqt = (Equation*)malloc(sizeof(Equation));
	pEqt->FirstItem = NULL;
	pEqt->next = EqtSet->FirstEquation;
	EqtSet->FirstEquation = pEqt;
	return pEqt;
}
//在一个方程组创建一个项;
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;
			//将整个方程存到->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] = '+';
			//----------------------------------------------------------------------------------
			//分割方程左右两部份;

			//找到等于号;
			DevideSign = EquationStrHead->szEquation;
			//等号左边没有东西;
			if (*DevideSign == '=') return FALSE;
			while (*DevideSign != '='&&*DevideSign != NULL) DevideSign++;
			//没有等于号;
			if (*DevideSign == NULL) return FALSE;
			//储存左边;
			memcpy(EquationStrHead->szEquationLeft+1, EquationStrHead->szEquation, DevideSign - EquationStrHead->szEquation);
			while (*DevideSign == '=' && *DevideSign != NULL) DevideSign++;
			// 等号右边没有东西;
			if (*DevideSign == NULL) return FALSE;
			strcpy(EquationStrHead->szEquationRight+1, DevideSign);
			//----------------------------------------------------------------------------------
			if (*pEnd != NULL)
				pEnd++;
			pStart = pEnd;
		}
		else
		{
			pEnd++;
		}
	}
	return TRUE;
}
//设置起始方程组;
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;
			else
				pStart = 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;						//无效的项;
					//第一次出现的元,在allunknownlist中添加;
					if (pItem->nType == TYPE_UNKNOWN && !IsInAllUnknown(pItem->szName))
					{
						Unknown*pUk = CreateUnknownInUkList(&AllUnknown);
						UnknownCount++;
						strcpy(pUk->Name, pItem->szName);
					}
					//分割右边的项每个系数乘-1;
					if (i == 1)
						pItem->k.Molecule *= -1;
					pStart = pEnd;
					if (pEnd != NULL)
						pEnd++;
				}
				else
				{
					pEnd++;
				}
			}
		}
	}
	return TRUE;
}
//化简每一项(约分);
void SimplyItem(Item*pItem)
{
	int MaxCommonFactor = GetMaxCommonFactor(pItem->k.Molecule, pItem->k.Denominator);
	pItem->k.Molecule /= MaxCommonFactor;
	pItem->k.Denominator /= MaxCommonFactor;
}
//是否为同类项;
BOOL IsSameClassItem(Item*pItem1, Item*pItem2)
{
	return ((pItem1->nType == pItem2->nType) && !strcmp(pItem1->szName, pItem2->szName));
}
//合并两项储存到第一项中;
void MergeItem(Item*pItem1, Item*pItem2)
{
	//计算分母的最小公倍数;
	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;
}
//化简方程式;
void SimplyEquation(Equation*eqt)
{
	int MaxCommonFactor = 0;
	//-----------------------------------合并同类项----------------------------;
	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;
			}
		}
	}
	//-------------------------------------清除系数为0的项---------------------------;
	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;
			else
				front = front->next;
			pItem = front->next;
		}
	}
	//每一项约分;
	for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next)
	{
		SimplyItem(pItem);
	}
	//获取所有项的最大公因数;
	for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next)
	{
		if (MaxCommonFactor == 0)
			MaxCommonFactor = pItem->k.Molecule;
		else
			MaxCommonFactor = GetMaxCommonFactor(MaxCommonFactor, pItem->k.Molecule);
	}
	//每一项同除以最大公因数;
	if (MaxCommonFactor != 1)
	{
		for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next)
		{
			pItem->k.Molecule /= MaxCommonFactor;
		}
	}
}
//获取常数项或元个数;
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;
}
//方程中是否存在某一个元;
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;
}
获取方程组出现次数最少的元,储存到Name中;
void GetLeastUnknown(EquationSet*EqtSet, char*Name,int size)
{
	Unknown *UnknInfo = NULL,*LeastUnknown = NULL,*pFindUnk = NULL,*pNewUnkn = NULL,*pUnknInfo = NULL;
	Equation*eqt;
	Item*pItem;
	//把所有的元储存到链表中并记录出现的次数;
	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)
	{
		//如果是第一个且出现次数大于1;
		if (LeastUnknown == NULL && pUnknInfo->value.Molecule > 1)
			LeastUnknown = pUnknInfo;
		//否则,如果小于leastUnknown则设置LeastUnknown==pUnknInfo;
		else if (pUnknInfo->value.Molecule > 1 && pUnknInfo->value.Molecule<LeastUnknown->value.Molecule)
			LeastUnknown = pUnknInfo;
	}
	memset(Name, 0, size);
	if (LeastUnknown != NULL)//每个元只出现了一次为空;
		strcpy(Name, LeastUnknown->Name);
	//释放内存;
	DelUnknownList(UnknInfo);
}
//化解每个方程并删除方程组中的空方程;
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;
			else
				front=front->next;
			Eqt=front->next;
		}
	}
}
//两个方程消元,反回新的方程;
Equation* ClearEquationUnknown(Equation*eqt1, Equation*eqt2,Item*pItem1,Item*pItem2)
{
	Item*pItem,*NewItem,*FindItem;
	Equation*NewEquation;
	int DenoMinCommonMultiple,MoleMinCommonMultiple,Eqt1Multiply,Eqt2Multiply;
	//记录两个方程相加还是相减;
	BOOL bChangeSign;
	bChangeSign = (pItem1->k.Molecule*pItem2->k.Molecule)>=0;
	//取分母最小公倍数;
	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;
	//取分子最小公倍数;
	MoleMinCommonMultiple = GetMinCommonMultiple(pItem1->k.Molecule, pItem2->k.Molecule);
	//计算第一个方程每一项要乘的数;
	Eqt1Multiply = MoleMinCommonMultiple / ABS(pItem1->k.Molecule);
	//计算第一个方程每一项要乘的数;
	Eqt2Multiply = MoleMinCommonMultiple / ABS(pItem2->k.Molecule);
	//给第一个方程的每一项乘上Eqt1Multiply;
	for (pItem = eqt1->FirstItem; pItem != NULL; pItem = pItem->next)
	{
		pItem->k.Molecule*=Eqt1Multiply;
	}
	//给第一个方程的每一项乘上Eqt1Multiply;
	for (pItem = eqt2->FirstItem; pItem != NULL; pItem = pItem->next)
	{
		pItem->k.Molecule*=Eqt2Multiply;
		//如果同号,将方程2所有的符号取反;
		if (bChangeSign)
		{
			pItem->k.Molecule*=-1;
		}
	}
	//储存生成的新方程;
	NewEquation = (Equation*)malloc(sizeof(Equation));
	memset(NewEquation,0,sizeof(Equation));
	//先把eqt1复制到NewEquation中;
	for (pItem = eqt1->FirstItem; pItem != NULL; pItem = pItem->next)
	{
		NewItem = CreateItemInEqt(NewEquation);
		memcpy(NewItem, pItem, sizeof(Item)-4/*减去四个字节(next指针)*/);
	}
	//遍历eqt2各个项,在NewEquation中查找是否存在,不存在添加,存在合并;
	for (pItem = eqt2->FirstItem; pItem != NULL; pItem = pItem->next)
	{
		FindItem = EqtExistItem(NewEquation, pItem->nType, pItem->szName);
		if (FindItem == NULL)		//不存在;
		{
			//在NewEquation中添加该项
			Item*NewItem = CreateItemInEqt(NewEquation);
			memcpy(NewItem, pItem, sizeof(Item)-4/*减去四个字节(next指针)*/);
		}
		else						//存在该项;
			MergeItem(FindItem, pItem);
	}
	SimplyEquation(eqt1);
	SimplyEquation(eqt2);
	SimplyEquation(NewEquation);
	return NewEquation;
}
//方程组开始消元;
void BeginEliminationUnknown()
{
	char LeastUnknown[32] = { 0 };
	while(1)
	{
		int EqtSetExist = 0;
		Equation*eqt1,*eqt2,*front;
		EquationSet*EqtSet = EquationSetHead;
		SimplyEquationSet(EqtSet);
		//找出出现次数最少的元;
		GetLeastUnknown(EqtSet, LeastUnknown, sizeof(LeastUnknown));
		//不存在出现次数最少的元;
		if (*LeastUnknown == '\0')
			break;
		for (eqt1 = EqtSet->FirstEquation, front = NULL; eqt1 != NULL;)
		{
			Item*FindItem1 = EqtExistItem(eqt1, TYPE_UNKNOWN, LeastUnknown);
			Item*FindItem2;
			//标记只创建一个下一个方程组;
			
			//如果不存在最少次数元,把这个方程放到下一个方程组;
			if (FindItem1 == NULL)
			{
				if(EqtSetExist==0)
				{
					CreateEquationSetInEqtSetList(&EquationSetHead);
					EqtSetExist=1;
				}
				//移动这个方程,下一个方程组是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						//如果这个方程存在出现最少次数元,则从下一个方程开始寻找;
			{
				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);
						//不存在下一个方程组添加;
						if (EqtSetExist==0)
						{
							CreateEquationSetInEqtSetList(&EquationSetHead);
							EqtSetExist=1;
						}
						NewEquation->next = EquationSetHead->FirstEquation;
						EquationSetHead->FirstEquation = NewEquation;
					}
				}
				if (front == NULL)
					front = EqtSet->FirstEquation;
				else
					front = front->next;
				eqt1 = front->next;
			}
		}
	}
}
//将方程组中的方程按未知项个数排序;
void SortEquation(EquationSet*EqtSet)
{
	//记录方程个数;
	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++)
		{
			//如果当前的方程式未知项项数多于下一项,交换位置;
			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;
				else
					front = front->next;
				CurEqt = front->next;
			}
		}
	}
}
//从EqtSet最后一组起设置确定量和变化量
BOOL SetDefinite(EquationSet*EqtSetHead)
{
	EquationSet*CurEqtSet;
	for (CurEqtSet = EqtSetHead; CurEqtSet != NULL; CurEqtSet = CurEqtSet->next)
	{
		Equation*eqt;
		SimplyEquationSet(CurEqtSet);
		//按项数多少排序;
		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);
					//值已经确定;
					if (FindUnknown != NULL)
					{
						//设为常数项;
						pItem->nType = TYPE_CONSTANT;
						memset(pItem->szName, 0, sizeof(pItem->szName));
						//分子相乘,分母相乘;
						pItem->k.Molecule*= FindUnknown->value.Molecule;
						pItem->k.Denominator*=FindUnknown->value.Denominator;
					}
				}
			}
			//化简一次;
			SimplyEquation(eqt);
			UnknownNum = GetConstOrUnknownNum(eqt,TYPE_UNKNOWN);
			ConstNum = GetConstOrUnknownNum(eqt,TYPE_CONSTANT);
			//所有项都消完;
			if (UnknownNum == 0 && ConstNum == 0)
				continue;
			//左边没有未知项,只有常数项且不等于0;
			if (UnknownNum == 0 && ConstNum != 0)
				return FALSE;
			//只有一个未知项,可以确定值;
			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;
				}
				//如果是被动变化量,尾插法;
				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;
					else
						pTail->next = pNew;
					memset(pNew,0,sizeof(Unknown));
				}
				else
					//头插法;
					pNew = CreateUnknownInUkList(&Definite);
				pNew->value.Molecule=pNew->value.Denominator=1;
				//复制名称;
				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)			//结果为负;
						pNew->value.Molecule*=-1;
				}
				continue;
			}
			//留一个被动变化值的位置;
			for (pItem = eqt->FirstItem; pItem != NULL; pItem = pItem->next)
			{
				if (pItem->nType == TYPE_UNKNOWN && !IsVaried(pItem->szName) && !Is_Varied(pItem->szName))
				{
					//还没有设置被动变化量;
					if(_VariedSet == 0)
					{
						//加到被动变化量中;
						Unknown*unk = CreateUnknownInUkList(&_Varied);
						strcpy(unk->Name, pItem->szName);
						_VariedSet = 1;
					}
					else
					{
						//加到主动变化量中;
						Unknown*unk = CreateUnknownInUkList(&Varied);
						unk->value.Molecule=1;
						unk->value.Denominator=1;
						strcpy(unk->Name, pItem->szName);
					}
				}
			}
		}
	}
	return TRUE;
}
//创建EquationSet的副本
EquationSet* CopyEquationSet()
{
	EquationSet*RetEquationSet = NULL,*NewCurEqtSet = NULL,*EqtSet;
	for (EqtSet = EquationSetHead; EqtSet != NULL; EqtSet = EqtSet->next)
	{
		Equation*eqt;
		//没有头,尾插法;
		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;
}
//保存结果;
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);
	}
}
//当存在主动变化值时用枚举法解出给定个数组解;
int Solve(Unknown * unknown)
{
	//没有主动变化量,都是确定的量;
	if (Varied == NULL)
		return SUCCESS;
	//主动变化量链表尾端,主动变化量已经设置好;
	if (unknown == NULL)
	{
		EquationSet*TempEquationSet;
		//已经解完,退出;
		if (CurSoluton >= MaxSolution)
			return SUCCESS;
		//创建方程组s的副本;
		TempEquationSet = CopyEquationSet();
		if (FALSE == SetDefinite(TempEquationSet))	//无解,退出;
		{
			//删除方程组s的副本;
			DelEquationSet(TempEquationSet);
			return FAIL;
		}
		else                                    //保存该组解;
		{
			CurSoluton++;
			SaveRet();
			//删除方程组s的副本;
			DelEquationSet(TempEquationSet);
			return NEXT;
		}
	}
	else                                                     //设置该主动变化量的值;
	{
		while (1)
		{
			int ret;
			//-----------------------------------------------------------------------------
			//在Definite中添加该项
			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中当前元及后面的项;
			for (_unk = Definite,front = NULL; _unk != NULL;)
			{
				Unknown*__unk;
				if (strcmp(_unk->Name, unknown->Name) == 0)
				{
					if (front == NULL)
						Definite = NULL;
					else
						front->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;
						//找到最后一个Varied,值加一;
						last = Varied;
						while (last->next != NULL)
							last = last->next;
						last->value.Molecule++;
					}
					else
						return NEXT;
				}
				else
					unknown->value.Molecule++;
			}
		}
	}
}
//结束;
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;
	//开始两两消元;
	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;
	}
	//----------------------取分母最小公倍数---------------------;
	for(uk = RetSolution->unknown;uk!=NULL;uk=uk->next)
	{
		if(MinCommonMultiple == 0)
			MinCommonMultiple = uk->value.Denominator;
		else
			MinCommonMultiple = GetMinCommonMultiple(uk->value.Denominator,MinCommonMultiple);
	}
	//----------------------通分-----------------------------;
	for(uk = RetSolution->unknown;uk!=NULL;uk=uk->next)
		uk->value.Molecule*=MinCommonMultiple/uk->value.Denominator;
	//----------------------------生成结果--------------------------;
	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");
	//--------------------------输出结果--------------------------;
	printf(szRet);
	//释放内存;
	EndChemistryEquationStringProcess();
	EndEquationSetSolve();
	return 0;
}

能力有限,用了2000多行代码
大神勿喷

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Suspend.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值