用栈来实现表达式求值

来源:互联网 发布:网络四大名著紫川 编辑:程序博客网 时间:2024/05/18 11:49
1、需求分析
设计一个程序,演示用算符优先法对算术表达式求值的过程。利用算符优先关系,实现对算术四则混合运算表达式的求值。
(1)输入的形式:表达式,例如2*(3+4)
     包含的运算符只能有'+' 、'-' 、'*' 、'/' 、'('、 ')';
(2)输出的形式:运算结果,例如2*(3+4)=14;
(3)程序所能达到的功能:对表达式求值并输出

2、系统设计
1、栈的抽象数据类型定义:
ADT Stack{
数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0}
数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,…,n}
          约定an端为栈顶,ai端为栈底
基本操作:
Push(&S,e)
初始条件:栈S已存在
操作结果:插入元素e为新的栈顶元素
Pop(&S,&e)
初始条件:栈S已存在且非空
操作结果:删除S的栈顶元素,并用e返回其值
}ADT Stack
3、各个模块的主要功能:
*Push(SC *s,char c):把字符压栈
*Push(SF *s,float f):把数值压栈
*Pop(SC *s):把字符退栈
*Pop(SF *s):把数值退栈
Operate(a,theta,b):根据theta对a和b进行'+' 、'-' 、'*' 、'/' 、'^'操作
In(Test,*TestOp):若Test为运算符则返回true,否则返回false
ReturnOpOrd(op,*TestOp):若Test为运算符,则返回此运算符在数组中的下标
precede(Aop,Bop):根据运算符优先级表返回Aop与Bop之间的优先级
EvaluateExpression(*MyExpression):用算符优先法对算术表达式求值


完整的程序代码如下:

[cpp] view plain copy
  1. #include"stdio.h"  
  2. #include"stdlib.h"   
  3. #include"string.h"   
  4. #include"math.h"  
  5. #define true 1   
  6. #define false 0   
  7. #define OPSETSIZE 8   
  8. typedef int Status;   
  9.   
  10. unsigned char Prior[8][8] =  
  11. // 运算符优先级表   
  12.     // '+' '-' '*' '/' '(' ')' '#' '^'   
  13.     /*'+'*/'>','>','<','<','<','>','>','<',   
  14.     /*'-'*/'>','>','<','<','<','>','>','<',   
  15.     /*'*'*/'>','>','>','>','<','>','>','<',   
  16.     /*'/'*/'>','>','>','>','<','>','>','<',   
  17.     /*'('*/'<','<','<','<','<','=',' ','<',   
  18.     /*')'*/'>','>','>','>',' ','>','>','>',   
  19.     /*'#'*/'<','<','<','<','<',' ','=','<',   
  20.     /*'^'*/'>','>','>','>','<','>','>','>'   
  21. };   
  22.   
  23. typedef struct StackChar  
  24. {  
  25.     char c;   
  26.     struct StackChar *next;   
  27. }SC;       //StackChar类型的结点SC  
  28.   
  29. typedef struct StackFloat  
  30. {  
  31.     float f;   
  32.     struct StackFloat *next;   
  33. }SF;       //StackFloat类型的结点SF  
  34.   
  35. SC *Push(SC *s,char c)          //SC类型的指针Push,返回p  
  36. {  
  37.     SC *p=(SC*)malloc(sizeof(SC));   
  38.     p->c=c;   
  39.     p->next=s;   
  40.     return p;   
  41. }   
  42.   
  43. SF *Push(SF *s,float f)        //SF类型的指针Push,返回p  
  44. {  
  45.     SF *p=(SF*)malloc(sizeof(SF));   
  46.     p->f=f;   
  47.     p->next=s;   
  48.     return p;   
  49. }   
  50.   
  51. SC *Pop(SC *s)    //SC类型的指针Pop  
  52. {  
  53.     SC *q=s;   
  54.     s=s->next;   
  55.     free(q);   
  56.     return s;   
  57. }   
  58.   
  59. SF *Pop(SF *s)      //SF类型的指针Pop  
  60. {  
  61.     SF *q=s;   
  62.     s=s->next;   
  63.     free(q);   
  64.     return s;   
  65. }   
  66.   
  67. float Operate(float a,unsigned char theta, float b)      //计算函数Operate  
  68. {  
  69.     switch(theta)  
  70.     {  
  71.     case '+'return a+b;   
  72.     case '-'return a-b;   
  73.     case '*'return a*b;   
  74.     case '/'return a/b;   
  75.     case '^'return pow(a,b);   
  76.     default : return 0;   
  77.     }   
  78. }   
  79.   
  80. char OPSET[OPSETSIZE]={'+','-','*','/','(',')','#','^'};   
  81.   
  82. Status In(char Test,char *TestOp)  
  83. {  
  84.     int Find=false;   
  85.     for (int i=0; i< OPSETSIZE; i++)  
  86.     {  
  87.         if(Test == TestOp[i])  
  88.             Find= true;   
  89.     }   
  90.     return Find;   
  91. }   
  92.   
  93. Status ReturnOpOrd(char op,char *TestOp)  
  94. {   
  95.     for(int i=0; i< OPSETSIZE; i++)  
  96.     {  
  97.         if (op == TestOp[i])  
  98.             return i;  
  99.     }  
  100. }  
  101.   
  102. char precede(char Aop, char Bop)  
  103. {   
  104.     return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];   
  105. }   
  106.   
  107. float EvaluateExpression(char* MyExpression)  
  108. {   
  109.     // 算术表达式求值的算符优先算法  
  110.     // 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合   
  111.     SC *OPTR=NULL;       // 运算符栈,字符元素   
  112.     SF *OPND=NULL;       // 运算数栈,实数元素   
  113.     char TempData[20];   
  114.     float Data,a,b;   
  115.     char theta,*c,Dr[]={'#','\0'};   
  116.     OPTR=Push(OPTR,'#');   
  117.     c=strcat(MyExpression,Dr);   
  118.     strcpy(TempData,"\0");//字符串拷贝函数   
  119.     while (*c!= '#' || OPTR->c!='#')  
  120.     {   
  121.         if (!In(*c, OPSET))  
  122.         {   
  123.             Dr[0]=*c;   
  124.             strcat(TempData,Dr);           //字符串连接函数   
  125.             c++;   
  126.             if (In(*c, OPSET))  
  127.             {   
  128.                 Data=atof(TempData);       //字符串转换函数(double)   
  129.                 OPND=Push(OPND, Data);   
  130.                 strcpy(TempData,"\0");   
  131.             }   
  132.         }   
  133.         else    // 不是运算符则进栈   
  134.         {  
  135.             switch (precede(OPTR->c, *c))  
  136.             {  
  137.             case '<'// 栈顶元素优先级低   
  138.                 OPTR=Push(OPTR, *c);   
  139.                 c++;   
  140.                 break;   
  141.             case '='// 脱括号并接收下一字符   
  142.                 OPTR=Pop(OPTR);   
  143.                 c++;   
  144.                 break;   
  145.             case '>'// 退栈并将运算结果入栈   
  146.                 theta=OPTR->c;OPTR=Pop(OPTR);   
  147.                 b=OPND->f;OPND=Pop(OPND);   
  148.                 a=OPND->f;OPND=Pop(OPND);   
  149.                 OPND=Push(OPND, Operate(a, theta, b));   
  150.                 break;   
  151.             } //switch  
  152.         }   
  153.     } //while   
  154.     return OPND->f;   
  155. //EvaluateExpression   
  156.   
  157. int main(void)  
  158. {   
  159.     char s[128];  
  160.     puts("请输入表达式:");   
  161.     gets(s);  
  162.     puts("该表达式的值为:");   
  163.     printf("%s\b=%g\n",s,EvaluateExpression(s));  
  164.     system("pause");  
  165.     return 0;  
  166. }  

     测试结果如下:

 

3
0 0
原创粉丝点击