📄 表达式求值.cpp
字号:
#include<string.h>
#include<stdio.h>
#include<ctype.h>
#include<math.h>
#include<malloc.h>
#include<stdlib.h>
#include<iostream.h>
#include<string.h>
#define prompt printf("Pb4801039>")
const max=300;
const stackinitsize=300;
const stackincrement=100;
double trans=1;
typedef struct
{char *elem;
int top;
int stacksize;
int increment;
}stack_C;
typedef struct
{double *elem;
int top;
int stacksize;
int increment;
}stack_F;
typedef struct lnode
{float data;
char oper;
struct lnode *next;
}lnode,*linklist;
int Error(char *s)
{printf("\n %s\n",s);
printf("\n");
return 0;
}
void initstack_C(stack_C &S,int maxsize=stackinitsize,int incresize=stackincrement)
{ S.elem=new char[maxsize];
S.top=-1;
S.stacksize=maxsize;
S.increment=incresize;}
void initstack_F(stack_F &S,int maxsize=stackinitsize,int incresize=stackincrement)
{ S.elem=new double[maxsize];
S.top=-1;
S.stacksize=maxsize;
S.increment=incresize;}
char gettop_C(stack_C S,char &e)
{if(S.top==-1) return '\0'; // Error("栈已空")
e=S.elem[S.top];
return e;}
void push_C(stack_C &S,char e)
{if(S.top==S.stacksize-1)
{ int newsize=S.stacksize+S.increment;
char *newbase=new char[newsize];
for(int i=0;i<S.stacksize;i++)
newbase[i]=S.elem[i];
delete S.elem;
S.elem=newbase;
S.stacksize+=S.increment;
}
S.elem[++S.top]=e;
}
void push_F(stack_F &S,double e)
{if(S.top==S.stacksize-1)
{ int newsize=S.stacksize+S.increment;
double *newbase=(double *)realloc(S.elem,newsize*sizeof(double));
S.elem=newbase;
S.stacksize+=S.increment;}
S.elem[++S.top]=e;
}
void pop_C(stack_C &S,char &e)
{ if(S.top==-1) Error("栈已空!");
e=S.elem[S.top--];
}
void pop_F(stack_F &S,double &e)
{ if(S.top==-1) Error("栈已空!");
e=S.elem[S.top--];
}
int stackempty_C(stack_C S)
{if(S.top==-1) return 1;
else return 0;
}
int stackempty_F(stack_F S)
{if(S.top==-1) return 1;
else return 0;
}
void info()
{system("title 小型表达式求值系统");system("color 0b");
printf("\n\n请输入表达式,可以使用函数和括号。\n\n");
printf("比如sin,cos,tan,sinh,cosh,tanh,ln,lg,exp,!,%%%等数学函数。 \n\n");
//printf("三角函数默认使用的是弧度制,但可以用declare deg/rad改变。\n");
//printf("还可以使用大中小括号({[()]}),但需注意优先级不要搞错。 \n");
printf("需要帮助请输入help, 若退出可以输入exit, 也可以直接回车。 \n\n");
printf("--------------------------欢迎使用---------------------------\n\n");
}
void help()
{printf("\n\n请输入表达式,可以使用函数,\n");
printf("比如sin,cos,tan,sinh,cosh,tanh,ln,lg,exp,!,%%%等函数。 \n");
printf("三角函数默认使用的是弧度制,但可以用declare命令改变。\n");
printf("格式为declare deg/rad;可以使用show命令察看当前设置。\n");
printf("还可以使用大中小括号({[()]}),但需注意优先级不要搞错。 \n");
printf("可以使用的命令有time,date,exit,cls,color xx 等。 \n");
printf("--------------------------欢迎使用---------------------------\n\n");
}
int fac(int n)
{int result=1;
if(n==0) return 1;
while(n>0) result*=n--;
return result;
}
int get(char exp[])
{int flag=1,i=0;char ch='c';
scanf("%c",&ch);
while(ch!='\n')
{ if(flag&&(ch=='-'||ch=='+')) exp[i++]='0';
else flag=0;
exp[i++]=ch;
if(ch=='(') flag=1;
scanf("%c",&ch);
}
exp[i]='\0';
if(!strcmp(exp,"help")) {help();return 0;}
else if(!strcmp(exp,"exit")) exit(0);
else if(!strcmp(exp,"time")) {system("time /t");return 0;}
else if(!strcmp(exp,"date")) {system("date /t");return 0;}
else if(!strcmp(exp,"cls")) {system("cls");printf("\n");return 0;}
else if(strstr(exp,"color")) {system(exp);return 0;}
else if(!strcmp(exp,"declare deg")) {trans=3.14159265/180;printf("已改为角度制。\n");return 0;}
else if(!strcmp(exp,"declare rad")) {trans=1;printf("已改为弧度制。\n");return 0;}
else if(!strcmp(exp,"show")) {if(trans==1) printf("现在为弧度制。\n");else printf("现在为角度制。\n");return 0;}
else {exp[i]='#';exp[i+1]='\0';return 1;}
}
int functionprocess(char exp[])
{char *ch=exp;char temp[200];char *pch;char *q=temp;int k=0;
while(*ch!='#')
{ if(!strchr("+-*/()^!%1234567890.",*ch))
switch(*ch)
{ case 's' : {q=temp;while((*ch=='i'||*ch=='h'||*ch=='n'||*ch=='s')&&++k<=3)
*q++=*ch++;if(*ch=='h') {*q='h';ch++;q++;}*q='\0';
if(strcmp(temp,"sin")==0)
{ *(ch-2)=*(ch-3)=' ';*(ch-1)='s'; }
else if(strcmp(temp,"sinh")==0)
{ *(ch-2)=*(ch-3)=*(ch-4)=' ';*(ch-1)='S';}
else return Error("Ilegal char!");k=0;break;}
case 'c' : {q=temp;while((*ch=='o'||*ch=='h'||*ch=='s'||*ch=='c')&&++k<=3)
*q++=*ch++;if(*ch=='h') {*q='h';ch++;q++;}*q='\0';
if(strcmp(temp,"cos")==0)
{ *(ch-2)=*(ch-3)=' ';*(ch-1)='c';}
else if(strcmp(temp,"cosh")==0)
{ *(ch-2)=*(ch-3)=*(ch-4)=' ';*(ch-1)='C';}
else return Error("Ilegal char!");k=0;break;}
case 't' : {q=temp;while((*ch=='a'||*ch=='n'||*ch=='h'||*ch=='t')&&++k<=3)
*q++=*ch++;if(*ch=='h') {*q='h';ch++;q++;}*q='\0';
if(strcmp(temp,"tan")==0)
{ *(ch-2)=*(ch-3)=' ';*(ch-1)='t';}
else if(strcmp(temp,"tanh")==0)
{ *(ch-2)=*(ch-3)=*(ch-4)=' ';*(ch-1)='T';}
else return Error("Ilegal char!");k=0;break;}
case 'l' : {q=temp;while((*ch=='g'||*ch=='n'||*ch=='l')&&++k<=2)
*q++=*ch++;*q='\0';
if(strcmp(temp,"lg")==0)
{ *(ch-2)=' ';*(ch-1)='l';}
else if(strcmp(temp,"ln")==0)
{ *(ch-2)=' ';*(ch-1)='L';}
else return Error("Ilegal char!");k=0;break;}
case 'e' : {q=temp;while((*ch=='x'||*ch=='p'||*ch=='e')&&++k<=3)
*q++=*ch++;*q='\0';
if(strcmp(temp,"exp")==0)
{ *(ch-2)=*(ch-3)=' ';*(ch-1)='e';}
else Error("Ilegal char!");k=0;break;}
default : return Error("存在非法字符!");} //end switch
if((*ch<'a')||(*ch>'z'))
ch++;
} //end while
if(strchr(exp,' ')) {
ch=exp;pch=temp;
while(*ch!='\0')
{ if(*ch!=' ') *pch++=*ch++;
else ch++;}
*pch='\0';
strcpy(exp,temp);}
return 1;
} // end functionprocess
int match(char *exp)
{int flag1=0,flag2=0;char *temp=exp;char ch=*temp++,e;stack_C S;initstack_C(S);
while(ch!='#')
switch(ch)
{ case '{' : push_C(S,ch);flag1=1;flag2=1;*(temp-1)='(';ch=*temp++;break;
case '[' : push_C(S,ch);flag1=0;flag2=1;*(temp-1)='(';ch=*temp++;break;
case '(' : push_C(S,ch);flag1=0;flag2=0;ch=*temp++;break;
case ')' : {if(stackempty_C(S)) return Error("有多余括号!");
else if(gettop_C(S,e)=='(') {pop_C(S,e);ch=*temp++;}
else return Error("括号不匹配!");break;}
case ']' : {if(stackempty_C(S))return Error("有多余括号");
else if(gettop_C(S,e)!='[') return Error("括号不匹配!");
else if(flag2) return Error("优先级错误!");
else {pop_C(S,e);*(temp-1)=')';ch=*temp++;}break;}
case '}' : {if(stackempty_C(S)) return Error("有多余括号");
else if(gettop_C(S,e)!='{') return Error("括号不匹配!");
else if((flag1)&&(flag2)) return Error("优先级错误!");
else {pop_C(S,e);*(temp-1)=')';ch=*temp++;}break;}
default : ch=*temp++;}
if(!stackempty_C(S)) return Error("有多余括号!");
return 1;
}
int precede(char c,char ch)
{char oper[]="#(+-+/*/^";char func[]="%!sctSCTLle";
char *p,*ph;
ph=strchr(oper,ch);
if(ph) p=strchr(ph,c);
if(strchr(func,c)&&strchr(func,ch)) return 0;
else if(strchr(func,c)) return 1;
else if(strchr(func,ch)) return 0;
else if(p>=ph) return 1;
else return 0;
}
void change(char *p,int &n,float &num)
{char data[20];char *q=data; n=0;
while((*p<='9'&&*p>='0')||(*p=='.'))
{ *q++=*p++;n++;}
*q='\0';
num=(float)atof(data);}
void insert(linklist &head,linklist &p,float e,char c='\0')
{linklist q=new lnode;
q->data=e;
q->oper=c;
q->next=NULL;
p->next=q;
p=q;}
int transform(linklist &suffix,char *exp)
{ int k=0;linklist p=suffix;char c;int n;float num;stack_C S;
initstack_C(S);push_C(S,'#');
while(!stackempty_C(S))
{ if(strchr("+-*/^()sScCtTeLl%!#",*exp)==0)
{ change(exp,n,num);
exp+=(n-1);
insert(suffix,p,num);}
else if(*exp=='(') push_C(S,*exp);
else if(*exp==')')
{ pop_C(S,c);
while(c!='(')
{ insert(suffix,p,0,c);pop_C(S,c);}
}
else {while(gettop_C(S,c)&&(precede(c,*exp)))
{ insert(suffix,p,0,c);pop_C(S,c);}
if(*exp!='#') push_C(S,*exp);}
exp++;}
return 1;
}
int value(stack_F &S,char ch)
{double a,b;
switch(ch)
{case '+' : pop_F(S,a);pop_F(S,b);push_F(S,a+b);break;
case '-' : pop_F(S,a);pop_F(S,b);push_F(S,b-a);break;
case '*' : pop_F(S,a);pop_F(S,b);push_F(S,a*b);break;
case '/' : pop_F(S,a);pop_F(S,b);if(!b) Error("div zero");push_F(S,b/a);break;
case '^' : pop_F(S,a);pop_F(S,b);push_F(S,pow(b,a));break;
case 'S' : pop_F(S,a);push_F(S,sinh(a));break;
case 's' : pop_F(S,a);push_F(S,sin(a*trans));break;
case 'c' : pop_F(S,a);push_F(S,cos(a*trans));break;
case 'C' : pop_F(S,a);push_F(S,cosh(a));break;
case 'e' : pop_F(S,a);push_F(S,exp(a));break;
case 'L' : pop_F(S,a);if(a<=0) Error("Log erro!");push_F(S,log(a));break;
case 'l' : pop_F(S,a);if(a<=0) Error("Log error!");push_F(S,log10(a));break;
case 't' : pop_F(S,a);push_F(S,tan(a*trans));break;
case 'T' : pop_F(S,a);push_F(S,tanh(a));break;
case '%' : pop_F(S,a);pop_F(S,b);push_F(S,fmod(b,a));break;
case '!' : pop_F(S,a);push_F(S,fac((int)a));break;
default : return Error("Invaid oper!");
}
}
double calc(linklist suffix)
{stack_F S; linklist p=suffix->next;double result;
initstack_F(S);
while(p&&p->oper!='#')
{ if(!p->oper) push_F(S,p->data);
else value(S,p->oper);
p=p->next;}
pop_F(S,result);
return result;
}
void main()
{double result;
char exp[90],temp[90];
linklist suffix=new lnode;
suffix->next=NULL;
info();
loof:prompt;
if (get(exp)){
strcpy(temp,exp);temp[strlen(temp)-1]='\0';
if(strcmp(exp,"#")==0) return;
if(match(exp))
if(functionprocess(exp))
if(transform(suffix,exp))
if(result=calc(suffix)){
printf("\n 结果为");
if(strlen(temp)<20)
printf("%s=",temp);
printf("%g\n\n",result);}}
goto loof;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -