数据结构---表达式求值

一.实验目的

   通过一个具体实际应用例子,加深对数据结构课程的理解,能够综合利用数据结构以及C语言的知识设计程序,应用到实际问题中去。

二.实验题目

常见的小型计算器可以通过输入一个由操作数操作符组成的表达式计算出结构,设计一个程序模拟上述功能。本实验要求至少建立两个栈一个运算符优先级比较表,按照运算法优先级的不同操作两个栈,最终实现整个表达式的求值。本程序可以移植到任何一个小型计算器中。

 三.实现提示

1.运算符优先级表如下图所示:

 

+

-

*

/

#

+

-

*

/

=

 

 

#

 

=

 

2.从键盘上输入的都是按照字符的形式,而实际的计算过程中需要将其转化成对应的操作符和操作数,将其转化可以通过对应的ASCII码表实现,通过查找ASCII码表来找出字符所对应的操作数以及操作符。

3.表达式中可能含有多位数以及带小数的数,对这种情况的处理主要是要通过一个子函数进行,依次读入字符据直到遇到下一个运算符结束,然后整体处理整个字符串,转化成数据。而对于带小数的情况则需要将整数部分和小数部分分开按照前述过程处理,最后再将两部分合并

四.思考及选做

   1.需要注意的是在程序实际运行的时候,对于有小数部分的情况计算的结果会出现截断误差,也就是说计算出的值有舍入情况,注意这一现象,深入理解计算机进行科学计算的本质。

 五.我的实现


[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #define  error 0  
  5. #define   ok   1  
  6. #define   overflow  -1  
  7. #define STACK_INIT_SIZE  100  
  8. #define STACKINCREMENT 10  
  9. #define OPSETSIZE  7  
  10. typedef int Status;  
  11. /* 
  12.   算符间的优先关系 
  13. */  
  14. char OPSET[OPSETSIZE]={'+','-','*','/','(',')','#'};  
  15. unsigned char Prior[7][7] = {       
  16.      '>','>','<','<','<','>','>',  
  17.    '>','>','<','<','<','>','>',  
  18.    '>','>','>','>','<','>','>',  
  19.    '>','>','>','>','<','>','>',   
  20.    '<','<','<','<','<','=',' ',  
  21.    '>','>','>','>',' ','>','>',  
  22.    '<','<','<','<','<',' ','='  
  23. };  
  24.   
  25. /* 
  26.   顺序栈结构模板 
  27. */  
  28. template <typename T>  
  29. struct SqStack  
  30. {  
  31.  T  *top;  
  32.  T  *base;  
  33.  int  stacksize;  
  34. };  
  35.   
  36. /* 
  37.   初始化栈函数模板 
  38. */  
  39. template <typename T1,typename T2>  
  40. Status InitStack(T1 &S)  
  41. {  
  42.  S.base=(T2 *)malloc(STACK_INIT_SIZE*sizeof(T2));  
  43.  if(!S.base)  exit (overflow);  
  44.  S.top=S.base;  
  45.  S.stacksize=STACK_INIT_SIZE;  
  46.  return ok;  
  47. }  
  48.   
  49. /* 
  50.   入栈函数模板 
  51. */  
  52. template <typename T1,typename T2>  
  53. Status Push(T1 &S,T2 e)  
  54. {  
  55.  if(S.top-S.base>=S.stacksize)  
  56.  {  
  57.   S.base=(T2 *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(T2));  
  58.      if(!S.base)  exit (overflow);  
  59.   S.top=S.base+S.stacksize;  
  60.   S.stacksize+=STACKINCREMENT;  
  61.  }  
  62.  *S.top++=e;  
  63.  return ok;  
  64. }  
  65.   
  66. /* 
  67.   出栈函数模板 
  68. */  
  69. template <typename T1,typename T2>  
  70. Status Pop(T1 &S,T2 &e)  
  71. {  
  72.  if(S.top==S.base) return error;  
  73.  e=*--S.top;  
  74.  return ok;  
  75. }  
  76.   
  77. /* 
  78.   获取栈顶元素模板 
  79. */  
  80. template <typename T1,typename T2>  
  81. T2 GetTop(T1 S)  
  82. {  
  83.  if(S.top==S.base)  
  84.   return error;  
  85.  else  
  86.   return *(S.top-1);  
  87.   
  88. }  
  89.   
  90. /* 
  91.   判断是否为运算符 
  92. */  
  93. Status In(char Test,char* TestOp) {  
  94.    bool Find=false;  
  95.    for (int i=0; i< OPSETSIZE; i++) {  
  96.       if (Test == TestOp[i]) Find= true;  
  97.    }  
  98.    return Find;  
  99. }  
  100.   
  101. /* 
  102.   运算  
  103. */  
  104. float Operate(float a,unsigned char theta, float b) {  
  105.    switch(theta) {  
  106.       case '+'return a+b;  
  107.       case '-'return a-b;  
  108.       case '*'return a*b;  
  109.       case '/'return a/b;  
  110.       default : return 0;  
  111.    }   
  112. }  
  113.   
  114. /* 
  115.   ReturnOpOrd和precede组合,判断运算符优先级 
  116. */  
  117. int ReturnOpOrd(char op,char* TestOp) {  
  118.    int i;  
  119.    for(i=0; i< OPSETSIZE; i++) {  
  120.       if (op == TestOp[i]) return i;  
  121.    }  
  122.    return 0;  
  123. }  
  124.   
  125. char precede(char Aop, char Bop) {  
  126.    return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];  
  127. }  
  128.   
  129. /*  
  130.    算术表达式求值的算符优先算法。 
  131.    设OPTR和OPND分别为运算符栈和运算数栈,OPSET为运算符集合。 
  132. */  
  133. float EvaluateExpression() {    
  134.      
  135.    SqStack<char>  OPTR;    // 运算符栈,字符元素  
  136.    SqStack<float> OPND;    // 运算数栈,实数元素  
  137.    char TempData[20];  
  138.    float Data,a,b;  
  139.    char theta,c,x,Dr[2];  
  140.      
  141.    InitStack<SqStack<char>,char> (OPTR);  
  142.    Push (OPTR, '#');  
  143.    InitStack <SqStack<float>,float>(OPND);  
  144.    strcpy(TempData,"\0");//将TempData置为空  
  145.    c=getchar();  
  146.    while (c!= '#' || GetTop<SqStack<char>,char>(OPTR)!= '#')  
  147.    {  
  148.       if (!In(c, OPSET))   
  149.    {  
  150.         Dr[0]=c;  
  151.         Dr[1]='\0';//存放单个数  
  152.          strcat(TempData,Dr);//将单个数连到TempData中,形成字符串  
  153.          c=getchar();  
  154.          if(In(c,OPSET))//如果遇到运算符,则将字符串TempData转换成实数,入栈,并重新置空  
  155.   
  156.    {  
  157.             Data=(float)atof(TempData);  
  158.             Push(OPND, Data);  
  159.             strcpy(TempData,"\0");  
  160.          }  
  161.       }   
  162.    else   
  163.    {   // 不是运算符则进栈  
  164.          switch (precede(GetTop<SqStack<char>,char>(OPTR), c)) {   
  165.             case '<':   // 栈顶元素优先权低  
  166.                  Push(OPTR, c);    
  167.                  c=getchar();  
  168.                  break;  
  169.             case '=':   // 脱括号并接收下一字符  
  170.                  Pop(OPTR, x);     
  171.                  c=getchar();  
  172.                  break;  
  173.             case '>':   // 退栈并将运算结果入栈  
  174.                  Pop(OPTR, theta);  
  175.                  Pop(OPND, b);    
  176.                  Pop(OPND, a);                        
  177.                  Push(OPND, Operate(a, theta, b));   
  178.                  break;  
  179.          }  
  180.       }  
  181.    }   
  182.    return GetTop<SqStack<float>,float>(OPND);  
  183. }  
  184.   
  185. int main()  
  186. {  
  187.  printf("请输入表达式,请以#结束:\n");  
  188.  printf("%f\n",EvaluateExpression());  
  189.  system("PAUSE");  
  190.  return 0;  
  191. }  
一、问题描述 在控制台下实现一个对算术表达式求值的模拟程序。 二、基本要求 该演示程序具有如下基本功能: (1) 表达式输入,以字符序列的形式从终端输入一个语法正确的数值表达式(float型),且表达式中只含有+、-、*、/、( 、)6 种运算符,输入格式如下: <变量><运算符><变量>……<回车> 例如表达式: 100+(15/3)*2 输入格式为: 100+(15/3)*2<回车> 注意: 输入的表达式中间不含空格。 (2) 表达式结果的输出,输出形式为: <表达式> = <结果> 例如表达式: 100+(15/3)*2 输出形式为: 100+(15/3)*2 = 110 注意: 此处的输出结果为整个表达式的数值结果。 (3) 数据合法性检验 主要是针对原表达式中除数为 0 的情况。 三、界面效果 表达式求值模拟程序 功能菜单: ============== [1] 输入表达式并求值 [0] 退出 ============== 请输入你的选择 (0~1):1 请输入一个表达式 : 100+(15/3)*2 计算结果如下: 100+(15/3)*2 = 110 请输入你的选择 (0~1):0 四、测试数据 (1) 8 = (2) 1+2+3+4 = (3) 88-1*5 = (4) 1024/4*8 = (5) 1024/(4*8) = (6) (20+2)*(6/2) = (7) 3-3-3 = (8) 80/(9-9) = (9) (6+2*(3+6*(6+6)) = (10) (((6+6)*6+3)*2+6)*2 = 五、实现提示 (1) 设置运算符栈和操作数栈辅助分析算符优先关系; (2) 在读入字符序列时,完成运算符和操作数的处理,以及相应运算; (3) 在识别处运算数的同时,要将其字符序列形式转化成 float 型数据形式; (4) 输入的字符序列中,操作数不一定是一位数,可能是多位数,如 16+32 ; (5) 使用 Lab3-1 实现的栈的 ADT 基本操作完成本次作业 ; (6) 在程序中会用到两类栈:操作数栈和运算符栈,分别为 float 型数据和字符型数据, 思考在同一个程序中如何处理两类不同的数据类型? (7) 算符之间的优先关系参考课本 P53 页表 3.1 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值