C语言利用前缀表达式实现复杂科学计算器

  • Post author:
  • Post category:其他


用C语言实现的科学计算器,支持2种常量,10种基本函数,Ans寄存器。相对来说拓展性应该是不错的,思路是首先化简复杂名称的函数名和常量名,然后把表达式转换成前缀表达式,再直接处理前缀表达式即可。因此对运算符和括号优先级的处理比较容易完美实现,执行效率也比较高,且无论输入表达式有多么复杂,只要确保输入缓冲区(定义在Analytic.h中)够大后面的都好说。

Analytic.c 运算库源文件,考虑到了移植方便的问题:
//Create Date: 2018-3-4  
//Author: Charming  
//File: Analytic.c  
//Version: 1.7.2  
//Last edit Date: 2018-3-13  
//Directions: 表达式解析库源文件  
//  v1.0.0: 基本前缀表达式转换  
//  v1.1.0: 支持区分正负号与加减运算符的功能  
//  v1.2.0: 新增额外的多字节函数化简,并支持转换相应的前缀表达式  
//  v1.3.0: 新增支持符号常量参与表达式转换  
//  v1.3.5: 区分正负号与加减运算符功能的完善  
//  v1.4.0: 增加计算功能  
//  v1.5.0: 增加函数计算功能  
//  v1.6.0: 增加常数项功能  
//  v1.6.2: 增强表达式错误辨别能力  
//  v1.6.5: 提高常数精度  
//  v1.7.0: 新增三角函数的预期计算结果趋近于0或者不存在时的单独处理功能  
//  v1.7.2: 优化常数项遇到负号时的计算问题  
//  v1.7.7: 解决单目运算符计算顺序的Bug

#include "Analytic.h"  
#include <string.h>  
#include <math.h>  

char *Expression = 0;//中缀表达式指针  
a_size_t E_Ptr = 0;//中缀表达式操作位置标记  

char *Polish_Notation = 0;//前缀表达式指针  
a_size_t P_Ptr = 0;//前缀表达式操作位置标记  

double Calc_ANS = 0;//答案寄存器  

					/*基本常数项(数值)Start*/
const_mode double _const_Euler_ = 2.718281828459045;//自然常数e  
const_mode double _const_Pai_ = 3.141592653589793;//圆周率π  
												  /*基本常数项(数值)End*/

												  /*基本常数项(符号)Start*/
const_mode char Ans[] = "Ans";//上一运算答案  
#define S_Ans 'A'  
const_mode char Pai[] = "Pai";//圆周率π的多字节符号  
#define S_Pai 'P'  
const_mode char Euler[] = "_e_";//自然常数,一般都使用e而不是_e_,  
								//复杂名的写法仅为避免名称重复陷入死循环,  
								//实际使用时直接用e即可  
#define S_Euler 'e'  
								/*基本常数项(符号)End*/

								/*基本函数项Start*/
const_mode char Ln[] = "ln";//自然对数  
#define S_In 'I'  
const_mode char Exp[] = "Exp";//自然指数  
#define S_Exp 'E'  
const_mode char Log[] = "log";//以10为底的对数  
#define S_Log 'L'  
const_mode char Sin[] = "Sin";//正弦函数  
#define S_Sin 's'  
const_mode char Cos[] = "Cos";//余弦函数  
#define S_Cos 'c'  
const_mode char Tan[] = "Tan";//正切函数  
#define S_Tan 't'  
const_mode char Sqrt[] = "Sqrt";//开方函数  
#define S_Sqrt 'Q'  
const_mode char ArcSin[] = "Arcsin";//反正弦函数  
#define S_ArcSin 'S'  
const_mode char ArcCos[] = "Arccos";//反余弦函数  
#define S_ArcCos 'C'  
const_mode char ArcTan[] = "Arctan";//反正切函数  
#define S_ArcTan 'T'  
									/*基本函数项End*/

const_mode char *ComplexOperators[] = {//多字节函数名列表,顺序从长到短,有利于逻辑实别  
	ArcSin, ArcCos, ArcTan, Exp, Log, Sin, Cos, Tan, Sqrt, Ln
};

const_mode char SimpleOperators[] = {//单字节函数名列表,与多字节顺序需一一对应  
	S_ArcSin, S_ArcCos, S_ArcTan, S_Exp, S_Log, S_Sin, S_Cos, S_Tan,S_Sqrt, S_In
};

const_mode char *ComplexConstants[] = {//多字节常量名列表,顺序从长到短,有利于逻辑实别  
	Ans, Pai, Euler
};

const_mode char SimpleConstants[] = {//单字节常量名列表,与多字节顺序需一一对应  
	S_Ans, S_Pai, S_Euler
};

struct {
	char data[SymbolMax];
	w_size_t top;
}Symbol_Stack;//运算符栈  

struct {
	double data[NumberMax];
	w_size_t top;
}Number_Stack;//运算符栈  

typedef enum
{
	Symbol, Number
}Stack_type;//栈类型  

typedef enum
{
	isNumber,
	isNumberOrDot,
	isBrackets,
	isBracketLeft,
	isBracketRight,
	isOperatorsLevel3,
	isOperatorsLevel2,
	isOperatorsLevel1,
	isOperatorsLevel0,
	isConstants
}Symbol_type;//符号类型  

void Init_Stack(Stack_type type)//堆栈初始化  
{
	switch (type)
	{
	case Symbol:
		Symbol_Stack.top = -1;
		break;
	case Number:
		Number_Stack.top = -1;
		break;
	default:
		break;
	}
}

Analytic_type Symbol_Push(void)//中缀表达式中的当前字符入栈  
{
	if (Symbol_Stack.top < SymbolMax - 1)
		Symbol_Stack.data[++Symbol_Stack.top] = Expression[E_Ptr--];
	else
		return Conv_OverFlow;
	return Conv_Ok;
}

Analytic_type Symbol_Pop(void)//从运算符栈出栈到前缀表达式  
{
	if (Symbol_Stack.top >= 0)
		Polish_Notation[++P_Ptr] = Symbol_Stack.data[Symbol_Stack.top--];
	else
		return Conv_Exception;
	return Conv_Ok;
}

w_size_t Get_StringLen(char *str, const w_size_t Maxlen)//计算表达式长度  
{
#if USESTRINGLIB == 0  
	w_size_t len = 0;
	while (str[len] != '\0' && len < Maxlen)
	{
		len++;
	}
	return len;
#else  
	return (w_size_t)strnlen(str, Maxlen);
#endif  
}

#if STRINGLIB_standard == 1  
char* my_strrev(char* s)
{
	char* h = s;
	char* t = s;
	char ch;

	while (*t++) {};
	t -= 2;//与t++抵消、回跳过结束符'\0'  

	while (h < t)//当h和t未重合时,交换它们所指向的字符  
	{
		ch = *h;
		*h++ = *t;    /* h向尾部移动 */
		*t-- = ch;    /* t向头部移动 */
	}
	return s;
}
#endif  

void Make_String_Reverse(char *str, const w_size_t Maxlen)//字符串反转  
{
	w_size_t len;
	len = Get_StringLen(str, Maxlen);
	if (str[len - 1] == ' ')
	{
		str[len - 1] = 0;
	}
#if STRINGLIB_standard == 1  
	my_strrev(str);
#else  
	strrev(str);
#endif  
}

unsigned char Check(char *chr, Symbol_type type)//判断字符或字符串的类型  
{
	a_size_t i;
	switch (type)
	{
	case isNumber:
		if (*chr >= '0' && *chr <= '9')
			return 1;
		break;
	case isNumberOrDot:
		if (*chr >= '0' && *chr <= '9' || *chr == '.')
			return 1;
		break;
	case isBrackets:
		if (*chr == '(' || *chr == ')')
			return 1;
		break;
	case isBracketLeft:
		if (*chr == '(')
			return 1;
		break;
	case isBracketRight:
		if (*chr == ')')
			return 1;
		break;
	case isOperatorsLevel0:
		for (i = 0; i < sizeof(SimpleOperators); i++)
			if (*chr == SimpleOperators[i])
				return 1;
		break;
	case isOperatorsLevel1:
		if (*chr == '^')
			return 1;
		break;
	case isOperatorsLevel2:
		if (*chr == '*' || *chr == '/')
			return 1;
		break;
	case isOperatorsLevel3:
		if (*chr == '+' || *chr == '-')
			return 1;
		break;
	case isConstants:
		for (i = 0; i < sizeof(SimpleConstants); i++)
			if (*chr == SimpleConstants[i])
				return 1;
		break;
	default:
		break;
	}
	return 0;
}

Analytic_type Convert_to_Polish(void)//中缀表达式到前缀表达式的转换程序  
{
	Analytic_type AnserReg;
	unsigned char tempflag;
	P_Ptr = -1;

	Init_Stack(Symbol);
	E_Ptr = (a_size_t)Get_StringLen(Expression, Exprlen);
	while (E_Ptr >= 0)//逆序处理  
	{
		if (Check(&Expression[E_Ptr], isNumber))//处理数值情况  
		{
			tempflag = 0;//这里tempflag用于处理一个特殊情况(见下面代码),  
						 //使用goto容易造成复杂的意外情况,因此改用单独设立的标志位和死循环配合实现  
			while (1)
			{
				while (tempflag == 1 || (E_Ptr >= 0) && Check(&Expression[E_Ptr], isNumberOrDot))
				{
					tempflag = 0;
					Polish_Notation[++P_Ptr] = Expression[E_Ptr--];//将数值或小数点转入前缀表达式  
				}
				if ((E_Ptr >= 0) && //中缀表达式中还有没处理的  
					((E_Ptr == 0 && Check(&Expression[E_Ptr], isOperatorsLevel3)) ||
						Check(&Expression[E_Ptr], isOperatorsLevel3) &&
						!(Check(&Expression[E_Ptr - 1], isNumber) || Check(&Expression[E_Ptr - 1], isConstants)) &&
						!Check(&Expression[E_Ptr - 1], isBracketRight)))
					//由于三级运算符('+' '-')可做正负号使用,因此对单独存在的三级运算符当做数的一部分处理,  
					//即如果当前字符是最后一个字符,且是三级运算符,或者这并不是最后一个字符,且下一个字符  
					//不是右括号、不是数字或常量的情况下,这个三级运算符需要当作数处理。  
					tempflag = 1;
				else
					break;
			}
			Polish_Notation[++P_Ptr] = ' ';//前缀表达式添加空格分隔符  
		}
		else if (Check(&Expression[E_Ptr], isConstants))//待处理的是常量  
		{
			Polish_Notation[++P_Ptr] = Expression[E_Ptr--];//将常量符号转入前缀表达式  
			if ((E_Ptr >= 0) && //中缀表达式中还有没处理的  
				((E_Ptr == 0 && Check(&Expression[E_Ptr], isOperatorsLevel3)) ||
					Check(&Expression[E_Ptr], isOperatorsLevel3) &&
					!(Check(&Expression[E_Ptr - 1], isNumber) || Check(&Expression[E_Ptr - 1], isConstants)) &&
					!Check(&Expression[E_Ptr - 1], isBracketRight)))
				//对符号单独处理,原理类似于常数的处理方法  
				Polish_Notation[++P_Ptr] = Expression[E_Ptr--];//将常量符号转入前缀表达式  
			Polish_Notation[++P_Ptr] = ' ';//前缀表达式添加空格分隔符  
		}
		else if (Check(&Expression[E_Ptr], isBracketRight))//待处理的字符是右括号  
		{
			if ((AnserReg = Symbol_Push()) != Conv_Ok)//压入运算符栈,如果异常,则返回异常情况,压栈过程同时E_Ptr也移动,不需要重复操作  
				return AnserReg;
		}
		else if (Check(&Expression[E_Ptr], isBracketLeft))//待处理的字符是左括号  
		{
			while (!Check(&Symbol_Stack.data[Symbol_Stack.top], isBracketRight))//如果运算符栈栈顶不是右括号  
			{
				if ((AnserReg = Symbol_Pop()) != Conv_Ok)//运算符出栈  
					return AnserReg;
				Polish_Notation[++P_Ptr] = ' ';//出一次加一个空格  
			}
			Symbol_Stack.data[Symbol_Stack.top--] = '\0';//封栈,删除栈顶外内容  
			E_Ptr--;//处理下一位  
		}
		else if (Check(&Expression[E_Ptr], isOperatorsLevel3))//待处理字符是'+'或'-'  
		{
			while (Symbol_Stack.top >= 0 &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel3) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isBracketRight))
				//运算符栈非空,且栈顶不是')' '+' '-'的时候要先出栈,实际上这里是比较优先级,'*' '/' '^'的优先级更高,所以要先出栈  
			{
				if ((AnserReg = Symbol_Pop()) != Conv_Ok)//运算符出栈到前缀表达式  
					return AnserReg;
				Polish_Notation[++P_Ptr] = ' ';//出一次加一个空格  
			}
			if ((AnserReg = Symbol_Push()) != Conv_Ok)//压栈  
				return AnserReg;
		}
		else if (Check(&Expression[E_Ptr], isOperatorsLevel2))//待处理字符是'*'或'/'  
		{
			while (Symbol_Stack.top >= 0 &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel3) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel2) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isBracketRight))
				//运算符栈非空,且栈顶不是')' '+' '-' '*' '/'的时候要先出栈,原理同上  
			{
				if ((AnserReg = Symbol_Pop()) != Conv_Ok)//运算符出栈到前缀表达式  
					return AnserReg;
				Polish_Notation[++P_Ptr] = ' ';//出一次加一个空格  
			}
			if ((AnserReg = Symbol_Push()) != Conv_Ok)//压栈  
				return AnserReg;
		}
		else if (Check(&Expression[E_Ptr], isOperatorsLevel1))//待处理字符是'^',原理同上  
		{
			while (Symbol_Stack.top >= 0 &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel3) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel2) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel1) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isBracketRight))
				//运算符栈非空,且栈顶不是')' '+' '-' '*' '/' '^'的时候要先出栈,原理同上  
			{
				if ((AnserReg = Symbol_Pop()) != Conv_Ok)//运算符出栈到前缀表达式  
					return AnserReg;
				Polish_Notation[++P_Ptr] = ' ';//出一次加一个空格  
			}
			if ((AnserReg = Symbol_Push()) != Conv_Ok)//压栈  
				return AnserReg;
		}
		else if (Check(&Expression[E_Ptr], isOperatorsLevel0))//若待处理的是一元运算符  
		{
			if (E_Ptr > 0 && //单目运算符前有值或括弧  
				Check(&Expression[E_Ptr - 1], isNumberOrDot) ||
				Check(&Expression[E_Ptr - 1], isBracketRight) ||
				Check(&Expression[E_Ptr - 1], isConstants))
				return Conv_MathError;
			while (Symbol_Stack.top >= 0 &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel3) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel2) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel1) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel0) &&
				!Check(&Symbol_Stack.data[Symbol_Stack.top], isBracketRight))
				//原理同上  
			{
				if ((AnserReg = Symbol_Pop()) != Conv_Ok)//运算符出栈到前缀表达式  
					return AnserReg;
				Polish_Notation[++P_Ptr] = ' ';//出一次加一个空格  
			}
			if ((AnserReg = Symbol_Push()) != Conv_Ok)//压栈  
				return AnserReg;
		}
		else//其他的东西就直接都忽略掉吧  
		{
			E_Ptr--;
		}
	}
	while (Symbol_Stack.top >= 0)//操作符栈没有变空,说明有操作符没有取出来  
	{
		if ((AnserReg = Symbol_Pop()) != Conv_Ok)//运算符出栈到前缀表达式  
			return AnserReg;
		Polish_Notation[++P_Ptr] = ' ';//出一次加一个空格  
	}
	Polish_Notation[++P_Ptr] = Symbol_Stack.data[++Symbol_Stack.top] = '\0';//最后结尾加一个截至符  
	Make_String_Reverse(Polish_Notation, Polishlen);
	return Conv_Ok;
}

Init_type Analytic_Init(Init_type type, char *address)//表达式初始化  
{
	switch (type)
	{
	case Init_Expression://初始化中缀表达式  
		Expression = address;
		break;
	case Init_Polish_Notation://初始化前缀表达式  
		Polish_Notation = address;
		break;
	default:
		return Init_Error;
	}
	return Init_Ok;
}


void ReplaceStringtoChar(char *str, const char *tar, const char chr)//替换表达式中的复杂函数名  
{
	w_size_t position;
	char *tarposition;
	w_size_t tarsize;
	tarsize = (w_size_t)strlen(tar);
	while ((tarposition = strstr(str, tar)) != NULL)
	{
		position = tarposition - str;
		str[position++] = chr;
		while (str[position + tarsize - 1] != 0)
		{
			str[position] = str[position + tarsize - 1];
			position++;
		}
		str[position] = 0;
	}
}

char *Analytic_Simplification(char *str)//复杂函数名化简功能  
{
	a_size_t i;
	for (i = 0; i < sizeof(SimpleOperators); i++)//替换操作符  
		ReplaceStringtoChar(str, ComplexOperators[i], SimpleOperators[i]);
	for (i = 0; i < sizeof(SimpleConstants); i++)//替换常量名  
		ReplaceStringtoChar(str, ComplexConstants[i], SimpleConstants[i]);
	return str;
}

double Store(char *str, w_size_t *p)//转换字符到浮点数  
{
	w_size_t j = *p - 1, i;
	double n = 0, m = 0;
	switch (str[*p])
	{
	case S_Ans:
		if (str[*p - 1] == '-')
		{
			*p = *p - 1;
			return (-1 * Calc_ANS);
		}
		else
			return Calc_ANS;
	case S_Pai:
		if (str[*p - 1] == '-')
		{
			*p = *p - 1;
			return (-1 * _const_Pai_);
		}
		else
			return _const_Pai_;
	case S_Euler:
		if (str[*p - 1] == '-')
		{
			*p = *p - 1;
			return (-1 * _const_Euler_);
		}
		else
			return _const_Euler_;
	default:
		break;
	}
	while (str[j] >= '0' && str[j] <= '9')
		j--;
	if (str[j] != '.')
		for (i = j + 1; i <= *p; i++)
			n = 10 * n + (str[i] - '0');
	else
	{
		for (i = j + 1; i <= *p; i++)
			m = m + pow(0.1, i - j) * (str[i] - '0');
		if (str[j] == '.')
		{
			*p = --j;
			while (str[j] >= '0' && str[j] <= '9')
				j--;
			for (i = j + 1; i <= *p; i++)
				n = 10 * n + (str[i] - '0');
		}
	}
	*p = j;
	if (str[*p] == '-') return(-(n + m));
	return(n + m);
}

Analytic_type Number_Push(w_size_t *i)//数值入栈  
{
	if (Number_Stack.top < NumberMax - 1)
		Number_Stack.data[++Number_Stack.top] = Store(Polish_Notation, i);
	else
		return Conv_OverFlow;
	return Conv_Ok;
}

double Clear_Infinitesimal(double ans)
{
	if (ans < 1e-10 && ans > -1e-10)
		return 0;
	else
		return ans;
}

double Clear_ComplexTan(double num)
{
	double r1, r2;
	int i = (int)(num / (_const_Pai_ / 2));
	r1 = num - i * (_const_Pai_ / 2) + 1e-15;
	r2 = (i + 1) * (_const_Pai_ / 2) - num + 1e-15;
	if (i % 2 != 0 &&
		((r1 > 0 && r1 < 1e-10) ||
		(r2 > 0 && r2 < 1e-10)))
		return NAN;
	return num;
}

Analytic_type Number_Pop(w_size_t i)//数值出栈  
{
	if (Number_Stack.top >= 0)
	{
		if (Polish_Notation[i] != ' ')
			switch (Polish_Notation[i])
			{
			case '+':
				Number_Stack.data[Number_Stack.top - 1] =
					Number_Stack.data[Number_Stack.top] + Number_Stack.data[Number_Stack.top - 1];
				Number_Stack.top--;
				break;
			case '-':
				Number_Stack.data[Number_Stack.top - 1] =
					Number_Stack.data[Number_Stack.top] - Number_Stack.data[Number_Stack.top - 1];
				Number_Stack.top--;
				break;
			case '*':
				Number_Stack.data[Number_Stack.top - 1] =
					Number_Stack.data[Number_Stack.top] * Number_Stack.data[Number_Stack.top - 1];
				Number_Stack.top--;
				break;
			case '/':
				Number_Stack.data[Number_Stack.top - 1] =
					Number_Stack.data[Number_Stack.top] / Number_Stack.data[Number_Stack.top - 1];
				Number_Stack.top--;
				break;
			case '^':
				Number_Stack.data[Number_Stack.top - 1] =
					pow(Number_Stack.data[Number_Stack.top], Number_Stack.data[Number_Stack.top - 1]);
				Number_Stack.top--;
				break;
			case S_In:
				Number_Stack.data[Number_Stack.top] = log(Number_Stack.data[Number_Stack.top]);
				break;
			case S_Log:
				Number_Stack.data[Number_Stack.top] = log10(Number_Stack.data[Number_Stack.top]);
				break;
			case S_Exp:
				Number_Stack.data[Number_Stack.top] = pow(_const_Euler_, Number_Stack.data[Number_Stack.top]);
				break;
			case S_Sin:
				Number_Stack.data[Number_Stack.top] = sin(Number_Stack.data[Number_Stack.top]);
				Number_Stack.data[Number_Stack.top] = Clear_Infinitesimal(Number_Stack.data[Number_Stack.top]);
				break;
			case S_Cos:
				Number_Stack.data[Number_Stack.top] = cos(Number_Stack.data[Number_Stack.top]);
				Number_Stack.data[Number_Stack.top] = Clear_Infinitesimal(Number_Stack.data[Number_Stack.top]);
				break;
			case S_Tan:
				Number_Stack.data[Number_Stack.top] = Clear_ComplexTan(Number_Stack.data[Number_Stack.top]);
				Number_Stack.data[Number_Stack.top] = tan(Number_Stack.data[Number_Stack.top]);
				Number_Stack.data[Number_Stack.top] = Clear_Infinitesimal(Number_Stack.data[Number_Stack.top]);
				break;
			case S_Sqrt:
				Number_Stack.data[Number_Stack.top] = sqrt(Number_Stack.data[Number_Stack.top]);
				break;
			case S_ArcSin:
				Number_Stack.data[Number_Stack.top] = asin(Number_Stack.data[Number_Stack.top]);
				break;
			case S_ArcCos:
				Number_Stack.data[Number_Stack.top] = acos(Number_Stack.data[Number_Stack.top]);
				break;
			case S_ArcTan:
				Number_Stack.data[Number_Stack.top] = atan(Number_Stack.data[Number_Stack.top]);
				break;
			}
	}
	else
		return Conv_MathError;
	return Conv_Ok;
}

Analytic_type Calculation_Results(void)
{
	Analytic_type res;
	w_size_t len, i;

	Init_Stack(Number);
	len = Get_StringLen(Polish_Notation, Polishlen);
	for (i = len - 1; i >= 0; i--)
	{
		if (Check(&Polish_Notation[i], isNumber) || Check(&Polish_Notation[i], isConstants) ||
			(Check(&Polish_Notation[i], isOperatorsLevel3) && Check(&Polish_Notation[i + 1], isNumber)))
		{
			if ((res = Number_Push(&i)) != Conv_Ok)
				return res;
		}
		else
		{
			if ((res = Number_Pop(i)) != Conv_Ok)
				return res;
		}
	}
	if (Symbol_Stack.top != 0 || Number_Stack.top != 0)
		return Conv_MathError;
	return Conv_Ok;
}

Analytic_type Analytic(Analytic_type type)//表达式解析  
{
	switch (type)
	{
	case Conv_to_Polish:
		return Convert_to_Polish();
	case Calc_Results:
		return Calculation_Results();
	default:
		break;
	}
	return Conv_Exception;
}

double Get_Answer(void)
{
	return (Calc_ANS = Number_Stack.data[0]);
}

Analytic.h 头文件,另外还包括几个重要的枚举类型:
//Create Date: 2018-3-4
//Author: Charming
//File: Analytic.h
//Directions: 表达式解析库头文件
//Last edit Date: 2018-3-6

#ifndef __ANALYTIC_H_
#define __ANALYTIC_H_

#define const_mode const

#define USESTRINGLIB 1
#define STRINGLIB_standard 1

#ifndef NULL
#define NULL 0
#endif

#define Exprlen 100
#define Polishlen 180
#define SymbolMax 80
#define NumberMax 50

typedef signed char a_size_t;
typedef signed short w_size_t;

typedef enum//初始化枚举类型
{
	Init_Expression,
	Init_Polish_Notation,
	Init_Ok,
	Init_Error
}Init_type;

typedef enum
{
	Conv_to_Polish,
	Calc_Results,
	Conv_Ok,
	Conv_MathError,
	Conv_OverFlow, 
	Conv_Exception
}Analytic_type;

Init_type Analytic_Init(Init_type type, char *address);
Analytic_type Analytic(Analytic_type type);
char *Analytic_Simplification(char *str);
double Get_Answer();

#endif

另外我贴上我测试用的 main.c,也可以作为使用方法的参考:
//Create Date: 2018-3-4
//Author: Charming
//File: Analytic.c
//Version: 1.7.2
//Last edit Date: 2018-3-15
//Directions: 测试源文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Analytic.h"

char E_String[Exprlen] = { 0 };
char P_String[Polishlen] = { 0 };

int main(void)
{
	Analytic_type res;
	Analytic_Init(Init_Expression, E_String);
	Analytic_Init(Init_Polish_Notation, P_String);
	while (1)
	{
		system("cls");
		printf("C语言利用前缀表达式实现复杂科学计算器\r\n");
		printf("Test Program Build : %s %s\r\n\r\n", __DATE__, __TIME__);
		printf("输入一个中缀表达式(退出请输入Exit):");
		gets_s(E_String, sizeof(E_String));
		if (strnicmp(E_String, "exit", 4) == 0)
			return 0;
		printf("化简后的中缀表达式: %s\r\n", Analytic_Simplification(E_String));
		if ((res = Analytic(Conv_to_Polish)) == Conv_Ok)
			res = Analytic(Calc_Results);
		switch (res)
		{
		case Conv_Ok:
			printf("前缀表达式: %s\r\n", P_String);
			printf("\r\n计算结果:%g\r\n\r\n", Get_Answer());
			break;
		case Conv_MathError:
			printf("\r\n数学错误!\r\n\r\n");
			break;
		case Conv_OverFlow:
			printf("\r\n堆栈溢出!\r\n\r\n");
			break;
		case Conv_Exception:
			printf("\r\n系统异常!\r\n\r\n");
			break;
		default:
			break;
		}
		system("pause");
	}
	return 0;
}

测试截图:


Mathematica验证:




版权声明:本文为MobiuX原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。