栈的应用之表达式求值code_legend

来源:互联网 发布:美人鱼影评知乎 编辑:程序博客网 时间:2024/05/03 04:45
/*
表达式求值
*/
#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "process.h"
#define STACKINITSIZE 100
#define STACKINCREMENT 10
typedef struct{
double *base;
double *top;
int stacksize;
}sshu;
typedef struct{
char *base;
char *top;
int stacksize;
}sfu;
char fuhao[8]={'+','-','*','/','(',')','^','#'};


//1初始化栈
     //存放数字的栈
void initstackshu(sshu &s)
{
s.base=(double *)malloc(STACKINITSIZE*sizeof(double));
if(!s.base)
exit(OVERFLOW);
s.top=s.base;
s.stacksize=STACKINITSIZE;
}
     //存放运算符的栈
void initstackfu(sfu &s)
{
s.base=(char *)malloc(STACKINITSIZE*sizeof(char));
if(!s.base)
exit(OVERFLOW);
s.top=s.base;
s.stacksize=STACKINITSIZE;
}


//2将数字和字符压栈
     //压字符
void pushfu(sfu &s,char e)
{
if(s.top-s.base>=s.stacksize)
{
s.base=(char *)realloc(s.base,(s.stacksize+STACKINCREMENT)*sizeof(char));
if(!s.base)
exit(OVERFLOW);
s.top=s.base+STACKINCREMENT;
s.stacksize+=STACKINCREMENT;
}
*s.top=e;
s.top++;
}
      //压数字
void pushshu(sshu &s,double e)
{
if(s.top-s.base>=s.stacksize)
{
s.base=(double *)realloc(s.base,(s.stacksize+STACKINCREMENT)*sizeof(double));
if(!s.base)
exit(OVERFLOW);
s.top=s.base+STACKINCREMENT;
s.stacksize+=STACKINCREMENT;
}
*s.top=e;
s.top++;
}


//3遍历栈顶元素
    //看符号栈顶元素
char gettopfu(sfu &s)
{
if(s.top==s.base)
{
printf("eroor1!");exit(0);
}
return *(s.top-1);
}
    //看数字栈顶元素
double gettopshu(sshu &s)
{
if(s.top==s.base)
{
printf("eroor2!");exit(0);
}
return *(s.top-1);
}


//4取栈顶元素
     //取符号栈顶元素
char popfu(sfu &s)
{
if(s.top==s.base)
{
printf("eroor3!");exit(0);
}
return *(--s.top);
}
     //取数字栈顶元素
double popshu(sshu &s)
{
if(s.top==s.base)
{
printf("error4!");exit(0);
}
return *(--s.top);
}


//5检查当前字符是否属于运算符
//很喜欢.将多个数用一个数组存储起来,再一个一个比较.
int in(char c,char *s)
{
int i;
for(i=0;i<8;i++)
if(c==s[i])
return 1;
return 0;
}
               //开始定义的符号集合如开头所示。但如果欲实现复杂的熟悉运算,可以考虑
               //将符号中的字符数量扩充   对于三角函数,对数函数等,可以考虑用不同的
               //简写字母表示函数。如输入的sin可以简写成s。然后再在程序中确立优先级别即可


//6当前字符与栈顶字符的优先级比较
      //共8种字符优先级别如下:
      //当前字符与栈顶字符比较:
      //(:0     +、-:1    *、/:2     ^:3     ):0
      //但若当前字符与栈顶字符相同时栈顶优先级低;'('遇到')'时二者优先级相同。
char compare(char s1,char s2)//s1表示栈顶符号,s2表示当前字符.
{
int a1,a2;
if(s1=='('&&s2==')')
return '=';
if(s2=='(')
return '<';
switch(s1)
{
case '(':a1=0;break;
case '+':
case '-':a1=1;break;
case '*':
case '/':a1=2;break;
    case '^':a1=3;break;
    case ')':a1=0;break;
case '#':a1=-1;break;
default: printf("error5!");exit(0);
}
switch(s2)
{
case '(':a2=0;break;
case '+':
case '-':a2=1;break;
case '*':
case '/':a2=2;break;
    case '^':a2=3;break;
    case ')':a2=0;break;
case '#':a2=-1;break;
default: printf("error6!");exit(0);
}
if(a1<a2)
return '<';
else  if(a1>a2)
return '>';
else if(a1==a2)
return '-';
}


//7单次计算
double calculate(double a,char t,double b)
{
double temp;
switch (t)
{
case '+':temp=a+b;printf("%10.5f+%10.5f=%10.5f\n",a,b,temp);return temp;
case '-':temp=a-b;printf("%10.5f-%10.5f=%10.5f\n",a,b,temp);return temp;
    case '*':temp=a*b;printf("%10.5f*%10.5f=%10.5f\n",a,b,temp);return temp;
    case '/':temp=a/b;printf("%10.5f/%10.5f=%10.5f\n",a,b,temp);return temp;
    case '^':temp=pow(a,b);printf("%10.5f^%10.5f=%10.5f\n",a,b,temp);return temp;
    default: printf("eroor7!");exit(0);
}
}


//8求值
double qiuzhi(char *s)
{
sshu shustack;
sfu fustack;
int i=0;
double a,b;
char t;
initstackshu(shustack);
initstackfu(fustack);
pushfu(fustack,'#');
while(s[i]!='#'||gettopfu(fustack)!='#')
{
double m=0,n=0;
if(!in(s[i],fuhao))
{
for(;!in(s[i],fuhao)&&s[i]!='.';i++)
m=10*m+(double)(s[i]-'0');
if(s[i]=='.')
{
int j=1;i++;
for(;!in(s[i],fuhao);i++,j++)
n+=pow(0.1,j)*(s[i]-'0');
}
pushshu(shustack,m+n);
}
else
switch(compare(gettopfu(fustack),s[i]))
{
   case '<':pushfu(fustack,s[i]);i++;break;
   case '=':popfu(fustack);i++;break;
   case '>': case '-':
t=popfu(fustack);b=popshu(shustack);a=popshu(shustack);pushshu(shustack,calculate(a,t,b));break;
   default:printf("eroor8!");exit(0);
}
}
return gettopshu(shustack);
}


//9主函数
int main()
{
char string[100]={0};
int d;
printf("欢迎使用简单表达式求值工具\n");
loop1:
printf("请输入表达式,用字符(、+、-*、/ 、^ 、)且是小写半角字符,以#结束输入:\n");
scanf("%s",string);
printf("%10.5f\n",qiuzhi(string));
loop2:
printf("继续使用吗?是请输入1,否请输入2\n");
scanf("%d",&d);
if(d==1)
goto loop1;
else
if(d==2)
{
printf("感谢使用\n");
exit(0);
}
else
{
printf("输入指令错误。\n");
goto loop2;
}
return 0;
}

0 0