实验二

实验二  表达式求值

 

院 、系

 海师计教系

 班级

计本二班

  

 200624101101

 姓名

 杨振平

完成日期

 2007-10-10

源程序名

 expression.cpp

 

一、题目

编制一个表达式求值的程序。

二、需求分析      

本程序在Windows环境下用用Visual C++编写,要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值

首先要了解算术四则运算的规则。即:

    1)先乘除,后加减;

    2)从左算到右;

3)先括号内,后括号外。

算符优先法就是根据这个运算优先关系的规定来实现对表达式的编译或解释执行的。

任何一个表达式都是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的,我们称它们为单词。一般地,操作数既可以是常数也可以是被说明为变量或常量的标识符;运算符可以分为算术运算符、关系运算符和逻辑运算符等三类;基本界限符有左右括号和表达式结束符等。为了叙述的简洁,我们仅讨论简单算术表达式的求值问题。这种表达式只含加、减、乘、除等四种运算符。

           我们把运算符和界限符统称为算符,它们构成的集合命名为OP。根据上述三条运算规则,在运算的每一步中,任意两个相继出现的算符op1op2之间的优先关系至多是下面三种关系之一:

                  op1<op2   opl的优先权低于op2

                  op1=op2   op1的优先权等于op2

                  op1>op2   op1的优先权高于op2

由规则3)+- *和/为op1时的优先性均低于‘(’但高于“)”,由 规则2),当op1=op2时,令op1>op2‘#’是表达式的结束符。为了算法简洁,在表达式的最左边也虚设一个‘#’构成整个表达式的一对括号。‘)’‘(’‘#’‘)’以及‘(’‘#’之间无优先关系,这是因为表达式中不允许它们相继出现,一旦遇到这种情况,则可以认为出现了语法错误。

           为实现算符优先算法,可以使用两个工作栈。一个称做OPTR,用以寄存运算符;另一个称做OPND,用以寄存操作数或运算结果。 

          

算法的基本思想是:

           1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;

           2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符,则和OPTR栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(OPTR栈的栈顶元素和当前读入的字符均为“#”)

二、概要设计

1)为了实现上述程序功能,需要定义单链表的抽象数据类型:

    ADT LinkList {

     数据对象:D={ai|ai∈IntegerSet,i=0,1,2,…,n,n≥0}

     数据关系:R={<ai,ai+1>|ai,ai+1 ∈D}

     基本操作:

        Status InitStack(SqStack &S)//初始化栈

        Status Push(SqStack &S,SElemType e) //入栈

char GetTop(SqStack S)//取栈顶元素

        int Pop(SqStack &S)//出栈

        int FindOpOrd(char op,char TestOp[])//查找取得的字符对应运算符表中的位置

char precede(char op1, char op2)//判断优先级并返回对应字符

int Operate(int a,int theta,int b)//字符解释计算函数

Status In(char Test,char TestOp[])//判断输入字符是否在运算符集合中

OperandType EvaluateExpression()// 算术表达式求值的算符优先算法。

 2)本程序包含7个函数:

    主函数main()

    运算符栈出栈初始化栈函数Status InitStack(SqStack &S)

    入栈函数Status Push(SqStack &S,SElemType e)

入栈取栈顶元素函数char GetTop(SqStack S)

    出栈函数int Pop(SqStack &S)

取得的字符对应运算符表中的位置函数int FindOpOrd(char op,char TestOp[])

判断优先级并返回对应字符函数char precede(char op1, char op2)

字符解释计算函数函数int Operate(int a,int theta,int b)

判断输入字符是否在运算符集合中函数Status In(char Test,char TestOp[])

算术表达式求值的算符优先算法函数OperandType EvaluateExpression()

  各函数间关系如下:

 

 main()

EvaluateExpression()

InitStack(SqStack &S)

Push(SqStack &S,SElemType e)

GetTop(SqStack S)

Pop(SqStack &S)

In(char Test,char TestOp[])

Operate(int a,int theta,int b)

FindOpOrd(charop,charTestOp[])

 

precede(char op1, char op2)

 

 

 

 

 

 

 

 

 

 

 


三、详细设计

为了实现概要设计中定义的所有的数据类型,对每个操作伪码算法;对主程序和其他模块也都需要写出伪码算法;画出系统结构图
  1)
该程序的功能是实现顺序栈的定义和操作。该程序包括定义的栈结构类型以及对每一种栈操作的具体的函数定义和主函数。

#define STACK_INIT_SIZE 100

#define STACK_INIT_LENGTH 10

#define STACKINCREMENT 10

#define OK 1

#define ERROR 0

#define OVERFLOW -2

#define OPSIZE 7

typedef int SElemType;

typedef int Status;

typedef char OperandType;

unsigned char Prior[7][7] = {

'>','>','<','<','<','>','>',

'>','>','<','<','<','>','>',

'>','>','>','>','<','>','>',

'>','>','>','>','<','>','>',

'<','<','<','<','<','=',' ',

'>','>','>','>',' ','>','>',

'<','<','<','<','<',' ','=',

};//定义优先级表

char OP[OPSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'};//定义运算符集合

typedef struct StackChar

{

    int *base;

    int *top;

    int stacksize;

}SqStack;

四、测试结果

1+2#

3

2+3#

5

五、调试分析

    在表达式求值函数中清楚了:getchar()<stdio.h>中定义为int

    因此c=getchar()c-48可以自动转化为字符型

经过反复的调试终于成功了!

             

六、 源程序(带注释)

#include  "malloc.h"

#include  "conio.h"

#include  "stdlib.h"

#include  "stdio.h"

#define STACK_INIT_SIZE 100

#define STACK_INIT_LENGTH 10

#define STACKINCREMENT 10

#define OK 1

#define ERROR 0

#define OVERFLOW -2

#define OPSIZE 7

typedef int SElemType;

typedef int Status;

typedef char OperandType;

unsigned char Prior[7][7] = {

'>','>','<','<','<','>','>',

'>','>','<','<','<','>','>',

'>','>','>','>','<','>','>',

'>','>','>','>','<','>','>',

'<','<','<','<','<','=',' ',

'>','>','>','>',' ','>','>',

'<','<','<','<','<',' ','=',

};//定义优先级表

char OP[OPSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'};//定义运算符集合

typedef struct StackChar

{

    int *base;

    int *top;

    int stacksize;

}SqStack;

Status InitStack(SqStack &S)//初始化栈

{

     S.base=(SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType ));

     if(!S.base) exit (OVERFLOW);

     S.top=S.base;

     S.stacksize=STACK_INIT_SIZE;

     return OK;

}

Status Push(SqStack &S,SElemType e) //入栈

{

if(S.top-S.base>=S.stacksize)

{

      S.base=(SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType ));

      if(!S.base) exit(OVERFLOW);

      S.top=S.base+S.stacksize;

      S.stacksize+=STACKINCREMENT;

}

*(S.top)=e;S.top++;

return OK;

}

 

 

char GetTop(SqStack S)//取栈顶元素

{

if(S.top==S.base) return ERROR;

return *(S.top-1); ;

}

 

int Pop(SqStack &S)//出栈

{

if(S.top==S.base) return ERROR;

return  *--S.top;

}

 

int FindOpOrd(char op,char TestOp[])//查找取得的字符对应运算符表中的位置

{

int j;

for(int i=0;i<OPSIZE;i++)

    if(op==TestOp[i]) j=i;

return j;

}

 

char precede(char op1, char op2)//判断优先级并返回对应字符

{

      return Prior[FindOpOrd(op1,OP)][FindOpOrd(op2,OP)];

}

 

int Operate(int a,int theta,int b)//字符解释计算函数

{

     switch(theta)

     {

         case '+': return a+b;break;

         case '-': return a-b;break;

         case '*': return a*b;break;

         case '/': return a/b;break;

         default : return 0;

     }

}

Status In(char Test,char TestOp[])//判断输入字符是否在运算符集合中

 {

int Find=ERROR;

  for (int i=0;i<OPSIZE;i++)

  {

      if(Test==TestOp[i]) Find=OK;

  }

return Find;

}

OperandType EvaluateExpression()

{// 算法3.4

// 算术表达式求值的算符优先算法。

// OPTROPND分别为运算符栈和运算数栈,OP为运算符集合

int a,b,c,theta;

SqStack OPTR,OPND;

InitStack(OPTR);

Push(OPTR,'#' );

InitStack(OPND);

c=getchar();

while(c!='#'||GetTop(OPTR)!='#')

{

     if(!In(c,OP)) // 不是运算符则进栈

     {

 

        Push(OPND,c-48);

        c=getchar();

     }

else

switch(precede(GetTop(OPTR),c))//判断优先级

{

      case'<':Push(OPTR,c);c=getchar();break; // 栈顶元素优先权低

      case'=':Pop(OPTR);c=getchar();break;  // 脱括号并接收下一字符

      case'>':theta=Pop(OPTR);b=Pop(OPND);a=Pop(OPND);Push(OPND,Operate(a,theta,b));break; // 退栈并将运算结果入栈

}

}

return GetTop(OPND);

}

void main()

{

    printf(“"请输入语法正确、不含有变量的整数表达式(表达式中的数字限为单位数)(#结束):/n"”);

    int e=EvaluateExpression();

    printf("%d/n",e);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值