我几年前初学C++的时候,曾经花了很长时间实现了表达式的解析和运算,支持函数和变量,还可以进行求导等操作,是我比较得意的成果,现在一翻看,却觉得满头雾水,大概是当初没有注释的习惯,又习惯于把大段大段的代码都塞在一个函数里吧。
这次决定重新进行一次实现,算是复习一下语法,也会使用一些最近才掌握的技巧。
这个文件用来声明所需的各种数据类型,我采用虚函数来实现运算,也就是说数值和变量也有求值运算。可以看到我用了联合来节省空间。
不打算使用后缀表达式数组来计算,而使用二叉树,二叉树的好处是,如果需要可以方便的实现懒惰求值、求导。当然这个就不打算这么做了,只是复习么。
/*
0 1 2 3 4 5 6 7 8 9
左括号 逗号 右括号 数值 变量 函数1p 函数2p 算符1p 算符2p 赋值符
*/
typedef double *Addrs;
typedef double (*Fun1p)(double);
typedef double (*Fun2p)(double,double);
enum AtomType{Is_Empty,Is_Lquot,Is_Comma,Is_Rquot,Is_Value,Is_Param,Is_Fun1p,Is_Fun2p,Is_Opr1p,Is_Opr2p,Is_Setvr};
struct myFac
{
union
{
char opr[8];
double *adr;
double vlu;
Fun1p fc1;
Fun2p fc2;
};
virtual double get()
{
return 0;
}
virtual double run(double x)
{
return 0 && x;
}
virtual double run(double x,double y)
{
return 0 && x && y;
}
virtual double set(double &x,double y)
{
return 0 && x && y;
}
};
struct myValue:myFac
{
virtual double get()
{
return vlu;
}
};
struct myParam:myFac
{
virtual double get()
{
return *adr;
}
};
struct myOpr1p:myFac
{
virtual double run(double x)
{
switch(opr[0])
{
case '+':return x;
case '-':return -x;
case '!':return x?0:1;
case '#':return x?1:0;
case '$':return x<0?-x:x;
case '@':return x<0?-1:x>0?1:0;
}
return 0;
}
};
struct myFun1p:myFac
{
virtual double run(double x)
{
return fc1(x);
}
};
struct myOpr2p:myFac
{
virtual double run(double x,double y)
{
switch(opr[0])
{
case '+':return x+y;
case '-':return x-y;
case '*':return x*y;
case '/':return x/y;
case '=':return x==y;
case '!':return x!=y;
case '&':return (bool)x && (bool)y;
case '|':return (bool)x || (bool)y;
case '>':return (opr[1]=='=')?(x>=y):(x>y);
case '<':return (opr[1]=='=')?(x<=y):(x<y);
}
return 0;
}
};
struct myFun2p:myFac
{
virtual double run(double x,double y)
{
return fc2(x,y);
}
};
struct mySetvr:myFac
{
virtual double set(double x,double y)
{
switch(opr[0])
{
case '=':x=y;break;
case '+':x+=y;break;
case '-':x-=y;break;
case '*':x*=y;break;
case '/':x/=y;break;
}
return x;
}
};
struct Atom
{
AtomType type;
myFac *data;
Atom *Lsun;
Atom *Rsun;
Atom()
{
type=Is_Empty;
data=NULL;
Lsun=NULL;
Rsun=NULL;
}
~Atom()
{
if(data)delete data;
}
};
void Remove(Atom *(&root))
{
if(root)
{
Remove(root->Lsun);
Remove(root->Rsun);
delete root;
root=NULL;
}
}
struct Lequ
{
Atom *equ;
Lequ *lst;
Lequ *nxt;
Lequ()
{
equ=NULL;
lst=NULL;
nxt=NULL;
}
~Lequ()
{
if(equ)Remove(equ);
}
};
void Remove(Lequ *(&root))
{
Lequ *sp,*md;
sp=root;
while(sp)
{
md=sp->nxt;
delete sp;
sp=md;
}
}