📄 expc.c
字号:
#include <stdio.h>
#include <math.h>
#define MAXLEN 400 //定义栈的长度
//定义运算符的值
#define OPRADD 1
#define OPRSUB 2
#define OPRMUL 3
#define OPRDIV 4
#define OPRMOD 5
#define OPRPOW 6
#define OPRLP 7
#define OPRRP 8
struct strdata //存储解析后的表达式
{
double d;
double (*f)();
}
;
//定义存储在结构 struct strdata中的是什么
#define ENDFLAG 255 //表示结束
#define DATAFLAG 0 //表示存储的是数据
#define OPRFLAG 1 //表示存储的是运算符
#define FUNCFLAG 2 //表示存储的是函数
#define FUNCNUM 16 //定义函数的总数目
#define FUNNAMELEN 5 //定义函数名的最长长度
extern int expcerr=0;
/*下面是表达式计算的主函数*/
double calcExp(char * ch);
/*把表达式解析到结构data中,和数组flag中*/
void parse(char *,struct strdata * data,int * flag);
/*把字符串形数字变成double型数字*/
double getvalue(char * ch,int * pi);
/*计算存储在data结构和数组flag中的表达式的值*/
double calcArray(struct strdata * data,int * flag);
/*计算算符的优先级 flag=0表示栈内,flag=1表示栈外*/
int prior(double ch,int flag);
double negate(double data);
/*两数相运算*/
double oprcalc(double data1,double data2,double opr);
static char * expcerrmsg[8] ={"",
"有非法字符!",
"语法错误!",
"括号不匹配!",
"长度过长",
"被0除!",
"函数的参数值超出范围!"};
void getfunc(struct strdata * data,char *,int *,int *);
double calcExp(char * ch)
{
double result;
struct strdata data[MAXLEN];
int flag[MAXLEN];
int i;
expcerr=0;
for(i=0;i<MAXLEN;i++)
data[i].f=NULL;
parse(ch,data,flag);
if (expcerr==0)
{
result=calcArray(data,flag);
return result;
}
else
return 0;
return -1;
}
void parse(char * ch,struct strdata * data,int * flag)
{
int i=0,j=0;
char ch1;
int v1,v2;
ch1=*ch;
while(ch1!='\0')
{
if (ch1==','|| ch1==' ')
{
i++;
ch1=ch[i];
continue;
}
if (ch1>=48 && ch1<=57)
{
flag[j]=DATAFLAG;
data[j].d=getvalue(&ch[i],&i);
}
else
{
//判断'-'是减号还是负号
if(ch1=='-')
{
if(i==0)
{
data[j].f=negate;
flag[j]=FUNCFLAG;
}
else
{
if(j==0)
{
data[j].d=OPRSUB;
flag[j]=OPRFLAG;
}
else
{
if(flag[j-1]==OPRFLAG && data[j-1].d!=OPRRP)
{
data[j].f=negate;
flag[j]=FUNCFLAG;
}
else
{
data[j].d=OPRSUB;
flag[j]=OPRFLAG;
}
}
}
goto end;
}
flag[j]=OPRFLAG;
switch(ch1)
{
case '+':
data[j].d=OPRADD;
break;
case '*':
data[j].d=OPRMUL;
break;
case '/':
data[j].d=OPRDIV;
break;
case '%':
data[j].d=OPRMOD;
break;
case '^':
data[j].d=OPRPOW;
break;
case '(':
data[j].d=OPRLP;
break;
case ')':
data[j].d=OPRRP;
break;
//如果是如果是其它字符,检查是否是函数
default:
if(j>0 )
{
//前面是数字,认为有一个*号
if(flag[j-1]==DATAFLAG)
{
flag[j]=OPRFLAG;
data[j].d=OPRMUL;
j++;
}
}
getfunc(&data[j],&ch[i],&i,&flag[j]);
if(expcerr!=0)
return ;
}
}
end:
j++;
i++;
if(i>MAXLEN)
{
expcerr=4;
return ;
}
ch1=ch[i];
}
flag[j]= ENDFLAG;
//检查是否有连续有算符情况
for(j=1;flag[j]!=ENDFLAG;j++)
{
if ((flag[j]==flag[j-1])==OPRFLAG)
{
if (data[j].d==OPRLP)
v2=1;
else
if (data[j].d==OPRRP)
v2=2;
else
v2=0;
if (data[j-1].d==OPRLP)
v1=1;
else
if (data[j-1].d==OPRRP)
v1=2;
else
v1=0;
if((v1==2 && v2==1)
|| (v1==1 && v2==2)
|| (v1==0 && v2==2)
|| (v1==1 && v2==0)
|| (v1==0 && v2==0)
)
{
expcerr=2;
return ;
}
}
}
//检查是否有左右括号数目不一致情况
j=0;
for(i=0;flag[i]!=ENDFLAG;i++)
{
if(flag[i]==OPRFLAG)
{
if (data[i].d==OPRLP)
j++;
else
if(data[i].d==OPRRP)
j--;
}
}
if (j!=0)
{
expcerr=3;
return ;
}
return ;
}
double getvalue(char * ch,int * pi)
{
double result,temp=10;
result=0;
while ((*ch)>=48 && (*ch)<=57)
{
result=result*10+(*ch - 48);
ch++;
(*pi)++;
}
if(*ch=='.')
{
ch++;
(*pi)++;
while ( (*ch)>=48 && (*ch)<=57)
{
result=result + (*ch -48 )/temp;
temp=temp*10;
ch++;
(*pi)++;
}
}
(*pi)--;
return result;
}
double calcArray(struct strdata * data,int * flag)
{
int i=0,j=-1,k=-1,m=0,n=0,bz=0;
struct strdata stackdata[MAXLEN];
double nextopr;
double result=0;
while (1)
{
if (flag[i]==DATAFLAG) //如果遇到操作数,进栈
{
j++;
stackdata[j].d=data[i].d;
stackdata[j].f=NULL;
i++;
continue;
}
//如果遇到(,进栈
if(flag[i]==OPRFLAG && data[i].d==OPRLP)
{
j++;
stackdata[j].d=data[i].d;
stackdata[j].f=NULL;
i++;
continue;
}
//如果是函数,进栈
if(flag[i]==FUNCFLAG)
{
j++;
stackdata[j].f=data[i].f;
i++;
continue;
}
//如果遇到),
if (flag[i]==OPRFLAG
&& data[i].d==OPRRP)
{
while (1)
{
while(stackdata[j-1].f!=NULL) //如果是函数
{
stackdata[j-1].d=(* stackdata[j-1].f)(stackdata[j].d);
stackdata[j-1].f=NULL;
j--;
}
if(stackdata[j-1].d==OPRLP)
break;
while (stackdata[j-1].d!=OPRLP && stackdata[j-1].f==NULL)//如果是运算符
{
stackdata[j-2].d=oprcalc(stackdata[j-2].d,stackdata[j].d,stackdata[j-1].d);
j=j-2;
if (j<=0)
break;
}
if(stackdata[j-1].d==OPRLP && stackdata[j-1].f==NULL)
break;
}
//删除栈中"("和跳过data[i].d中的")"
j--;
stackdata[j].d=stackdata[j+1].d;
stackdata[j].f=NULL;
i++;
if (j<=0)
continue;
//如果出栈后前一个是函数,继续出栈运算
if (stackdata[j-1].f!=NULL)
while (stackdata[j-1].f!=NULL)
{
stackdata[j-1].d=(* stackdata[j-1].f)(stackdata[j].d);
stackdata[j-1].f=NULL;
j--;
if (j<=0)
break;
}
continue;
}
//如果遇到一般操作符
if (flag[i]==OPRFLAG
&& data[i].d!=OPRLP
&& data[i].d!=OPRRP)
{
//如果后面是操作符或函数,操作符入栈
if (flag[i+1]==OPRFLAG ||flag[i+1]==FUNCFLAG )
{
j++;
stackdata[j].d=data[i].d;
stackdata[j].f=NULL;
i++;
continue;
}
else
{
//其后不是操作符和函数,是数值时,下一个肯定是操作符和函数
if (data[i+2].d!=OPRRP) //下一个不是)时,且没有结束时入栈
{
nextopr=data[i+2].d;
//没有结束
if (flag[i+2]!=ENDFLAG)
{
if (prior(data[i].d,0) - prior(nextopr,1) <0 )
{
j++;
stackdata[j].d=data[i].d;
stackdata[j].f=NULL;
i++;
continue;
}
}
//结束或后面的优先级低于前面的出栈计算
j++;
stackdata[j].d=data[i].d;
stackdata[j].f=NULL;
i++;
j++;
stackdata[j].d=data[i].d;
stackdata[j].f=NULL;
i++;
while (1)
{
if(j<=0)
break;
if (stackdata[j-1].f==NULL) //栈中不是函数
{
if (prior(stackdata[j-1].d,0) - prior(nextopr,1) >=0)
{
stackdata[j-2].d=oprcalc(stackdata[j-2].d,stackdata[j].d,stackdata[j-1].d);
j=j-2;
}
else
break;
}
else //栈中是函数
{
stackdata[j-1].d=(* stackdata[j-1].f)(stackdata[j].d);
stackdata[j-1].f=NULL;
j--;
}
}
continue;
}
else
{//其后一个操作符是)
j++;
stackdata[j].d=data[i].d;
stackdata[j].f=NULL;
i++;
j++;
stackdata[j].d=data[i].d;
stackdata[j].f=NULL;
i++;
while (stackdata[j-1].d!=OPRLP)
{
stackdata[j-2].d=oprcalc(stackdata[j-2].d,stackdata[j].d,stackdata[j-1].d);
j=j-2;
}
//删除栈中(和跳过data[i].d中的)
j--;
stackdata[j].d=stackdata[j+1].d;
stackdata[j].f=NULL;
i++;
if (j<=0)
continue;
//如果出栈后前一个是函数,继续出栈运算
if (stackdata[j-1].f!=NULL)
while (stackdata[j-1].f!=NULL)
{
stackdata[j-1].d=(* stackdata[j-1].f)(stackdata[j].d);
stackdata[j-1].f=NULL;
j--;
if (j<=0)
break;
}
continue;
}
}
}
if (flag[i]==ENDFLAG)
{
if(j==0)
return stackdata[j].d;
while (1)
{
if(j<=0)
return stackdata[j].d;
if (stackdata[j-1].f==NULL) //栈中不是函数
{
stackdata[j-2].d=oprcalc(stackdata[j-2].d,stackdata[j].d,stackdata[j-1].d);
j=j-2;
}
else //栈中是函数
{
stackdata[j-1].d=(* stackdata[j-1].f)(stackdata[j].d);
stackdata[j-1].f=NULL;
j--;
}
}
}
}
return result;
}
int prior(double opr,int flag)
{
int iopr=(int)opr;
switch(iopr)
{
case OPRADD:
return 1;
case OPRSUB:
return 1;
case OPRMUL:
return 2;
case OPRDIV:
return 2;
case OPRMOD:
return 2;
case OPRPOW:
return 3;
case OPRLP:
if(flag)
return 9;
else
return 0;
case OPRRP:
if(flag)
return 0;
else
return 9;
}
return -1;
}
double oprcalc(double data1,double data2,double opr)
{
int iopr=(int)opr;
switch(iopr)
{
case OPRADD:
return (data1+data2);
case OPRSUB:
return (data1-data2);
case OPRMUL:
return (data1*data2);
case OPRDIV:
if (data2==0)
{
expcerr=6;
return 0;
}
else
{
return (data1/data2);
}
case OPRMOD:
return fmod(data1,data2);
case OPRPOW:
return pow(data1,data2);
}
return 0;
}
void getfunc(struct strdata * data,char * ch,int *pi,int *pflag)
{
int i,j,flag;
char * funcname[FUNCNUM]={"abs","acos","asin"
,"atan","cos","cosh"
,"exp","log"
,"log10","sin"
,"sinh","tan","tanh"
,"sqrt","ceil","floor"
};
double (*pfun[FUNCNUM])()={fabs,acos,asin
,atan,cos,cosh
,exp,log
,log10,sin
,sinh,tan,tanh
,sqrt,ceil,floor
};
char temp[FUNNAMELEN+1];
for(i=0;i<=FUNNAMELEN;i++)
temp[i]='\0';
for(i=0;ch[i]!='(' && i<=FUNNAMELEN;i++)
{
temp[i]=ch[i];
}
if (i>FUNNAMELEN)
{
expcerr=1;
return ;
}
(*pi)=(*pi)+i-1;
for(i=0;i<FUNCNUM;i++)
{
flag=1;
for(j=0;j<=FUNNAMELEN && funcname[i][j]!='\0';j++)
{
if (temp[j]!=funcname[i][j])
{
flag=0;
break;
};
}
if (funcname[i][j]=='\0' && temp[j]=='\0' &&flag==1)
{
data->f=pfun[i];
(*pflag)=FUNCFLAG;
break;
}
}
if (i<FUNCNUM)
{
expcerr=0;
return ;
}
expcerr=1;
return ;
}
double negate(double data)
{
return -data;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -