热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

用C语言实现的科学计算器,支持2种常量,10种基本函数,Ans寄存器。相对来说拓展性应该是不错的,思路是首先化简复杂名称的函

用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
#include 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 }Analytic_type Symbol_Pop(void)//从运算符栈出栈到前缀表达式
{if (Symbol_Stack.top >= 0)Polish_Notation[++P_Ptr] = Symbol_Stack.data[Symbol_Stack.top--];elsereturn 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 #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 }
#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 >&#61; &#39;0&#39; && *chr <&#61; &#39;9&#39;)return 1;break;case isNumberOrDot:if (*chr >&#61; &#39;0&#39; && *chr <&#61; &#39;9&#39; || *chr &#61;&#61; &#39;.&#39;)return 1;break;case isBrackets:if (*chr &#61;&#61; &#39;(&#39; || *chr &#61;&#61; &#39;)&#39;)return 1;break;case isBracketLeft:if (*chr &#61;&#61; &#39;(&#39;)return 1;break;case isBracketRight:if (*chr &#61;&#61; &#39;)&#39;)return 1;break;case isOperatorsLevel0:for (i &#61; 0; i }Analytic_type Convert_to_Polish(void)//中缀表达式到前缀表达式的转换程序
{Analytic_type AnserReg;unsigned char tempflag;P_Ptr &#61; -1;Init_Stack(Symbol);E_Ptr &#61; (a_size_t)Get_StringLen(Expression, Exprlen);while (E_Ptr >&#61; 0)//逆序处理 {if (Check(&Expression[E_Ptr], isNumber))//处理数值情况 {tempflag &#61; 0;//这里tempflag用于处理一个特殊情况(见下面代码)&#xff0c; //使用goto容易造成复杂的意外情况&#xff0c;因此改用单独设立的标志位和死循环配合实现 while (1){while (tempflag &#61;&#61; 1 || (E_Ptr >&#61; 0) && Check(&Expression[E_Ptr], isNumberOrDot)){tempflag &#61; 0;Polish_Notation[&#43;&#43;P_Ptr] &#61; Expression[E_Ptr--];//将数值或小数点转入前缀表达式 }if ((E_Ptr >&#61; 0) && //中缀表达式中还有没处理的 ((E_Ptr &#61;&#61; 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)))//由于三级运算符(&#39;&#43;&#39; &#39;-&#39;)可做正负号使用&#xff0c;因此对单独存在的三级运算符当做数的一部分处理&#xff0c; //即如果当前字符是最后一个字符&#xff0c;且是三级运算符&#xff0c;或者这并不是最后一个字符&#xff0c;且下一个字符 //不是右括号、不是数字或常量的情况下&#xff0c;这个三级运算符需要当作数处理。 tempflag &#61; 1;elsebreak;}Polish_Notation[&#43;&#43;P_Ptr] &#61; &#39; &#39;;//前缀表达式添加空格分隔符 }else if (Check(&Expression[E_Ptr], isConstants))//待处理的是常量 {Polish_Notation[&#43;&#43;P_Ptr] &#61; Expression[E_Ptr--];//将常量符号转入前缀表达式 if ((E_Ptr >&#61; 0) && //中缀表达式中还有没处理的 ((E_Ptr &#61;&#61; 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)))//对符号单独处理&#xff0c;原理类似于常数的处理方法 Polish_Notation[&#43;&#43;P_Ptr] &#61; Expression[E_Ptr--];//将常量符号转入前缀表达式 Polish_Notation[&#43;&#43;P_Ptr] &#61; &#39; &#39;;//前缀表达式添加空格分隔符 }else if (Check(&Expression[E_Ptr], isBracketRight))//待处理的字符是右括号 {if ((AnserReg &#61; Symbol_Push()) !&#61; Conv_Ok)//压入运算符栈&#xff0c;如果异常&#xff0c;则返回异常情况&#xff0c;压栈过程同时E_Ptr也移动&#xff0c;不需要重复操作 return AnserReg;}else if (Check(&Expression[E_Ptr], isBracketLeft))//待处理的字符是左括号 {while (!Check(&Symbol_Stack.data[Symbol_Stack.top], isBracketRight))//如果运算符栈栈顶不是右括号 {if ((AnserReg &#61; Symbol_Pop()) !&#61; Conv_Ok)//运算符出栈 return AnserReg;Polish_Notation[&#43;&#43;P_Ptr] &#61; &#39; &#39;;//出一次加一个空格 }Symbol_Stack.data[Symbol_Stack.top--] &#61; &#39;\0&#39;;//封栈&#xff0c;删除栈顶外内容 E_Ptr--;//处理下一位 }else if (Check(&Expression[E_Ptr], isOperatorsLevel3))//待处理字符是&#39;&#43;&#39;或&#39;-&#39; {while (Symbol_Stack.top >&#61; 0 &&!Check(&Symbol_Stack.data[Symbol_Stack.top], isOperatorsLevel3) &&!Check(&Symbol_Stack.data[Symbol_Stack.top], isBracketRight))//运算符栈非空&#xff0c;且栈顶不是&#39;)&#39; &#39;&#43;&#39; &#39;-&#39;的时候要先出栈&#xff0c;实际上这里是比较优先级&#xff0c;&#39;*&#39; &#39;/&#39; &#39;^&#39;的优先级更高&#xff0c;所以要先出栈 {if ((AnserReg &#61; Symbol_Pop()) !&#61; Conv_Ok)//运算符出栈到前缀表达式 return AnserReg;Polish_Notation[&#43;&#43;P_Ptr] &#61; &#39; &#39;;//出一次加一个空格 }if ((AnserReg &#61; Symbol_Push()) !&#61; Conv_Ok)//压栈 return AnserReg;}else if (Check(&Expression[E_Ptr], isOperatorsLevel2))//待处理字符是&#39;*&#39;或&#39;/&#39; {while (Symbol_Stack.top >&#61; 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))//运算符栈非空&#xff0c;且栈顶不是&#39;)&#39; &#39;&#43;&#39; &#39;-&#39; &#39;*&#39; &#39;/&#39;的时候要先出栈&#xff0c;原理同上 {if ((AnserReg &#61; Symbol_Pop()) !&#61; Conv_Ok)//运算符出栈到前缀表达式 return AnserReg;Polish_Notation[&#43;&#43;P_Ptr] &#61; &#39; &#39;;//出一次加一个空格 }if ((AnserReg &#61; Symbol_Push()) !&#61; Conv_Ok)//压栈 return AnserReg;}else if (Check(&Expression[E_Ptr], isOperatorsLevel1))//待处理字符是&#39;^&#39;&#xff0c;原理同上 {while (Symbol_Stack.top >&#61; 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))//运算符栈非空&#xff0c;且栈顶不是&#39;)&#39; &#39;&#43;&#39; &#39;-&#39; &#39;*&#39; &#39;/&#39; &#39;^&#39;的时候要先出栈&#xff0c;原理同上 {if ((AnserReg &#61; Symbol_Pop()) !&#61; Conv_Ok)//运算符出栈到前缀表达式 return AnserReg;Polish_Notation[&#43;&#43;P_Ptr] &#61; &#39; &#39;;//出一次加一个空格 }if ((AnserReg &#61; Symbol_Push()) !&#61; 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 >&#61; 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 &#61; Symbol_Pop()) !&#61; Conv_Ok)//运算符出栈到前缀表达式 return AnserReg;Polish_Notation[&#43;&#43;P_Ptr] &#61; &#39; &#39;;//出一次加一个空格 }if ((AnserReg &#61; Symbol_Push()) !&#61; Conv_Ok)//压栈 return AnserReg;}else//其他的东西就直接都忽略掉吧 {E_Ptr--;}}while (Symbol_Stack.top >&#61; 0)//操作符栈没有变空&#xff0c;说明有操作符没有取出来 {if ((AnserReg &#61; Symbol_Pop()) !&#61; Conv_Ok)//运算符出栈到前缀表达式 return AnserReg;Polish_Notation[&#43;&#43;P_Ptr] &#61; &#39; &#39;;//出一次加一个空格 }Polish_Notation[&#43;&#43;P_Ptr] &#61; Symbol_Stack.data[&#43;&#43;Symbol_Stack.top] &#61; &#39;\0&#39;;//最后结尾加一个截至符 Make_String_Reverse(Polish_Notation, Polishlen);return Conv_Ok;
}Init_type Analytic_Init(Init_type type, char *address)//表达式初始化
{switch (type){case Init_Expression://初始化中缀表达式 Expression &#61; address;break;case Init_Polish_Notation://初始化前缀表达式 Polish_Notation &#61; 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 &#61; (w_size_t)strlen(tar);while ((tarposition &#61; strstr(str, tar)) !&#61; NULL){position &#61; tarposition - str;str[position&#43;&#43;] &#61; chr;while (str[position &#43; tarsize - 1] !&#61; 0){str[position] &#61; str[position &#43; tarsize - 1];position&#43;&#43;;}str[position] &#61; 0;}
}char *Analytic_Simplification(char *str)//复杂函数名化简功能
{a_size_t i;for (i &#61; 0; i }double Store(char *str, w_size_t *p)//转换字符到浮点数
{w_size_t j &#61; *p - 1, i;double n &#61; 0, m &#61; 0;switch (str[*p]){case S_Ans:if (str[*p - 1] &#61;&#61; &#39;-&#39;){*p &#61; *p - 1;return (-1 * Calc_ANS);}elsereturn Calc_ANS;case S_Pai:if (str[*p - 1] &#61;&#61; &#39;-&#39;){*p &#61; *p - 1;return (-1 * _const_Pai_);}elsereturn _const_Pai_;case S_Euler:if (str[*p - 1] &#61;&#61; &#39;-&#39;){*p &#61; *p - 1;return (-1 * _const_Euler_);}elsereturn _const_Euler_;default:break;}while (str[j] >&#61; &#39;0&#39; && str[j] <&#61; &#39;9&#39;)j--;if (str[j] !&#61; &#39;.&#39;)for (i &#61; j &#43; 1; i <&#61; *p; i&#43;&#43;)n &#61; 10 * n &#43; (str[i] - &#39;0&#39;);else{for (i &#61; j &#43; 1; i <&#61; *p; i&#43;&#43;)m &#61; m &#43; pow(0.1, i - j) * (str[i] - &#39;0&#39;);if (str[j] &#61;&#61; &#39;.&#39;){*p &#61; --j;while (str[j] >&#61; &#39;0&#39; && str[j] <&#61; &#39;9&#39;)j--;for (i &#61; j &#43; 1; i <&#61; *p; i&#43;&#43;)n &#61; 10 * n &#43; (str[i] - &#39;0&#39;);}}*p &#61; j;if (str[*p] &#61;&#61; &#39;-&#39;) return(-(n &#43; m));return(n &#43; m);
}Analytic_type Number_Push(w_size_t *i)//数值入栈
{if (Number_Stack.top }double Clear_Infinitesimal(double ans)
{if (ans <1e-10 && ans > -1e-10)return 0;elsereturn ans;
}double Clear_ComplexTan(double num)
{double r1, r2;int i &#61; (int)(num / (_const_Pai_ / 2));r1 &#61; num - i * (_const_Pai_ / 2) &#43; 1e-15;r2 &#61; (i &#43; 1) * (_const_Pai_ / 2) - num &#43; 1e-15;if (i % 2 !&#61; 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 >&#61; 0){if (Polish_Notation[i] !&#61; &#39; &#39;)switch (Polish_Notation[i]){case &#39;&#43;&#39;:Number_Stack.data[Number_Stack.top - 1] &#61;Number_Stack.data[Number_Stack.top] &#43; Number_Stack.data[Number_Stack.top - 1];Number_Stack.top--;break;case &#39;-&#39;:Number_Stack.data[Number_Stack.top - 1] &#61;Number_Stack.data[Number_Stack.top] - Number_Stack.data[Number_Stack.top - 1];Number_Stack.top--;break;case &#39;*&#39;:Number_Stack.data[Number_Stack.top - 1] &#61;Number_Stack.data[Number_Stack.top] * Number_Stack.data[Number_Stack.top - 1];Number_Stack.top--;break;case &#39;/&#39;:Number_Stack.data[Number_Stack.top - 1] &#61;Number_Stack.data[Number_Stack.top] / Number_Stack.data[Number_Stack.top - 1];Number_Stack.top--;break;case &#39;^&#39;:Number_Stack.data[Number_Stack.top - 1] &#61;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] &#61; log(Number_Stack.data[Number_Stack.top]);break;case S_Log:Number_Stack.data[Number_Stack.top] &#61; log10(Number_Stack.data[Number_Stack.top]);break;case S_Exp:Number_Stack.data[Number_Stack.top] &#61; pow(_const_Euler_, Number_Stack.data[Number_Stack.top]);break;case S_Sin:Number_Stack.data[Number_Stack.top] &#61; sin(Number_Stack.data[Number_Stack.top]);Number_Stack.data[Number_Stack.top] &#61; Clear_Infinitesimal(Number_Stack.data[Number_Stack.top]);break;case S_Cos:Number_Stack.data[Number_Stack.top] &#61; cos(Number_Stack.data[Number_Stack.top]);Number_Stack.data[Number_Stack.top] &#61; Clear_Infinitesimal(Number_Stack.data[Number_Stack.top]);break;case S_Tan:Number_Stack.data[Number_Stack.top] &#61; Clear_ComplexTan(Number_Stack.data[Number_Stack.top]);Number_Stack.data[Number_Stack.top] &#61; tan(Number_Stack.data[Number_Stack.top]);Number_Stack.data[Number_Stack.top] &#61; Clear_Infinitesimal(Number_Stack.data[Number_Stack.top]);break;case S_Sqrt:Number_Stack.data[Number_Stack.top] &#61; sqrt(Number_Stack.data[Number_Stack.top]);break;case S_ArcSin:Number_Stack.data[Number_Stack.top] &#61; asin(Number_Stack.data[Number_Stack.top]);break;case S_ArcCos:Number_Stack.data[Number_Stack.top] &#61; acos(Number_Stack.data[Number_Stack.top]);break;case S_ArcTan:Number_Stack.data[Number_Stack.top] &#61; atan(Number_Stack.data[Number_Stack.top]);break;}}elsereturn Conv_MathError;return Conv_Ok;
}Analytic_type Calculation_Results(void)
{Analytic_type res;w_size_t len, i;Init_Stack(Number);len &#61; Get_StringLen(Polish_Notation, Polishlen);for (i &#61; len - 1; i >&#61; 0; i--){if (Check(&Polish_Notation[i], isNumber) || Check(&Polish_Notation[i], isConstants) ||(Check(&Polish_Notation[i], isOperatorsLevel3) && Check(&Polish_Notation[i &#43; 1], isNumber))){if ((res &#61; Number_Push(&i)) !&#61; Conv_Ok)return res;}else{if ((res &#61; Number_Pop(i)) !&#61; Conv_Ok)return res;}}if (Symbol_Stack.top !&#61; 0 || Number_Stack.top !&#61; 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 &#61; Number_Stack.data[0]);
}



Analytic.h 头文件&#xff0c;另外还包括几个重要的枚举类型&#xff1a;

//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 50typedef 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&#xff0c;也可以作为使用方法的参考&#xff1a;

//Create Date: 2018-3-4
//Author: Charming
//File: Analytic.c
//Version: 1.7.2
//Last edit Date: 2018-3-15
//Directions: 测试源文件#include
#include
#include
#include "Analytic.h"char E_String[Exprlen] &#61; { 0 };
char P_String[Polishlen] &#61; { 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) &#61;&#61; 0)return 0;printf("化简后的中缀表达式: %s\r\n", Analytic_Simplification(E_String));if ((res &#61; Analytic(Conv_to_Polish)) &#61;&#61; Conv_Ok)res &#61; 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数学错误&#xff01;\r\n\r\n");break;case Conv_OverFlow:printf("\r\n堆栈溢出&#xff01;\r\n\r\n");break;case Conv_Exception:printf("\r\n系统异常&#xff01;\r\n\r\n");break;default:break;}system("pause");}return 0;
}



测试截图&#xff1a;




Mathematica验证&#xff1a;




推荐阅读
  • HDU 2871 内存管理问题(线段树优化)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871。本题涉及内存管理操作,包括重置、申请、释放和查询内存块。通过使用线段树进行高效管理和维护。 ... [详细]
  • KMP算法是一种高效的字符串模式匹配算法,能够在不进行回溯的情况下完成匹配,其时间复杂度为O(m+n),其中m和n分别为文本串和模式串的长度。本文将详细介绍KMP算法的工作原理,并提供C语言实现。 ... [详细]
  • 本文探讨了如何使用pg-promise库在PostgreSQL中高效地批量插入多条记录,包括通过事务和单一查询两种方法。 ... [详细]
  • 1、字符型常量字符型常量指单个字符,是用一对单引号及其所括起来的字符表示。例如:‘A’、‘a’、‘0’、’$‘等都是字符型常量。C语言的字符使用的就是 ... [详细]
  • 本文详细解析了 offset、client 和 page 坐标系统的不同之处。offset 是相对于当前元素的边界框的距离,与滚动条无关;client 是相对于可视区域(viewport)的距离,也与滚动条无关;page 则是相对于整个文档的距离,受滚动条位置影响。 ... [详细]
  • 本文详细探讨了Java中的ClassLoader类加载器的工作原理,包括其如何将class文件加载至JVM中,以及JVM启动时的动态加载策略。文章还介绍了JVM内置的三种类加载器及其工作方式,并解释了类加载器的继承关系和双亲委托机制。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • KMP算法是处理字符串匹配的一种高效算法它首先用O(m)的时间对模板进行预处理,然后用O(n)的时间完成匹配。从渐进的意义上说,这样时间复 ... [详细]
  • java文本编辑器,java文本编辑器设计思路
    java文本编辑器,java文本编辑器设计思路 ... [详细]
  • 本文介绍了如何使用JFreeChart库创建一个美观且功能丰富的环形图。通过设置主题、字体和颜色等属性,可以生成符合特定需求的图表。 ... [详细]
  • 本文详细探讨了Java命令行参数的概念、使用方法及在实际编程中的应用,包括如何通过命令行传递参数给Java程序,以及如何在Java程序中解析这些参数。 ... [详细]
  • 本文详细介绍了Linux内核中misc设备驱动框架的实现原理及应用方法,包括misc设备的基本概念、驱动框架的初始化过程、数据结构分析以及设备的注册与注销流程。 ... [详细]
  • 本题探讨在特定条件下如何通过选择瓶子以最大化从火星人处获取的燃料量。 ... [详细]
  • 深入解析Android中的SQLite数据库使用
    本文详细介绍了如何在Android应用中使用SQLite数据库进行数据存储。通过自定义类继承SQLiteOpenHelper,实现数据库的创建与版本管理,并提供了具体的学生信息管理示例代码。 ... [详细]
  • 本文详细介绍了 Kubernetes 集群管理工具 kubectl 的基本使用方法,涵盖了一系列常用的命令及其应用场景,旨在帮助初学者快速掌握 kubectl 的基本操作。 ... [详细]
author-avatar
安茂友恢复_172
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有