思路:
1:从字符串中获取中缀表达式
2:中缀表达式转换为后缀表达式
3:用后缀表达式计算结果
总体:
定义一个计算器处理类 作为对外唯一接口 class Calc_tag
获取计算的字符串 void WhatToCalc(const char *str);
计算 double Calc();
具体:
定义一个结构 保存 符号和数值
struct My_Token_tag
{
int type; //类型 1为数字 ,2为符号,3为函数
union
{
double value; // 数字的值
Sig_tag *sig; //符号或函数
};
};
其中Sig_tag为
typedef double (*My_Fun)(int n,double *p); 调用的函数类型
struct Sig_tag
{
char sig[10]; // 符号的名字 如 +- sin cos 之类
int prioriy; //优先级
int pragmanum; //当前符号或函数的参数个数
My_Fun fun; //该符号或函数的调用操作 比如 + 调用+的函数f_plus
Sig_tag():sig{0},prioriy(0),pragmanum(0),fun(0){}
Sig_tag(const char *s1,int p1,int pp1,My_Fun fun1);
Sig_tag operator = (Sig_tag s1);
Sig_tag(const Sig_tag &s1);
bool IsEmpty();
};
一些常用的函数 自己可以拓展补充
double f_plus(int n,double *p);
double f_dec(int n,double *p);
double f_mum(int n,double *p);
double f_div(int n,double*p);
double f_mod(int n,double*p);
double f_qf(int n,double *p);
double f_zs(int n,double *p);
//**********************************
double f_sqrt(int n,double *p);
double f_exp(int n,double *p);
double f_ln(int n,double *p);
double f_log(int n,double *p);
double f_sin(int n,double *p);
double f_cos(int n,double *p);
double f_tan(int n,double *p);
double f_atan2(int n,double *p);
double f_asin(int n,double *p);
double f_acos(int n,double *p);
double f_atan(int n,double *p);
具体操作:
class Calc_tag
{
public:
Calc_tag();
~Calc_tag();
void WhatToCalc(const char *str); 要计算的表达式 不用“”=“ ”结束
double Calc(); 对外计算
void AddSig(Sig_tag sig1); 用于拓展
void AddSig(const char *sig1,int p1,int pp1,My_Fun func1); 用于拓展
void ToBackBDS(); 转换为后缀表达式
void PickTokens(); 提取token ,匹配优先级
double RealCalc(); 计算后缀表达式
std::deque<My_Token_tag> & GetBDS() { return bds; } 用于拓展
std::deque<My_Token_tag> & GetBackBDS() { return tkbds; } 用于拓展
private:
std::vector<Sig_tag> basesig; 基本的符号库
std::vector<Sig_tag> funcsions; 函数库可以拓展
char *cacledstr;
std::deque<My_Token_tag> bds; 表达式 token的队列
std::deque<My_Token_tag>tkbds; 后缀表达式的队列
protected:
int IsBaseSig(Sig_tag & s1); 是否符号
int IsBaseSig(const char *s1);
int IsFuncSig(const char *s1); 是否是函数
int IsFuncSig(Sig_tag &s1);
Sig_tag GetBySig1(const char *pstr); 取得Sig_tag结构
Sig_tag GetBySig2(const char *pstr);
};
要点:
处理 - 号 有歧义 什么时候是减 什么时候是负
对于函数的处理 (,) 分别该怎么执行
清理程序的申请内存避免内存泄漏
其他
资源里有两个工程文件 一个是LIB 还有个是测试
用VS2017 编辑的 里面的属性和 计算器库 位置要修改一下避免出错