实验二

实验二  表达式求值

 


院 、系


 海师计教系


 班级


计本二班


学   号


 200624101101


 姓名


 杨振平


完成日期


 2007-10-10


源程序名


 expression.cpp

 

一、题目

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

二、需求分析      

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

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

    1)先乘除,后加减;

    2)从左算到右;

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

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

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

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

                  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

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

// 设OPTR和OPND分别为运算符栈和运算数栈,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);

}

时间: 2024-08-29 19:56:29

实验二的相关文章

数据结构教程 第十二课 实验二 循环链表实验

本课主题: 实验二 循环链表实验 教学目的: 掌握单向链表的实现方法 教学重点: 单向链表的存储表示及操作 教学难点: 单向链表的操作实现 授课内容: 一.单向链表的存储表示 C源程序 #include<stdio.h> #include<malloc.h> #include<conio.h> #define ERROR 0 #define OK 1 #define EQUAL 1 #define OVERFLOW -1 #define LIST_INIT_SIZE 1

linux实验二

实验2 Linux文件系统 一.实验目的 通过实验掌握Linux中文件管理的基本概念,包括常用命令格式.文件类型.目录结构等,初步了解有关文件安全方面的知识..   二.实验内容1.使用pwd,cd,ls等命令浏览文件系统.2.使用cat,cp,mv,head,tail,rm等命令查看和操作文件.3.使用find,grep命令进行文件查找和模式匹配.4.使用chmod命令修改文件的权限.   三.         实验报告 1.              简要说明实验的目的.任务与设备 2.  

实验二 8位加法器设计

一.实验目的 熟悉利用QuartusⅡ的图形编辑输入法设计简单组合电路,掌握层次化设计方法,并通过8位全加器的设计,进一步熟悉利用EDA软件进行数字系统设计的流程. 二.实验仪器与器材 计算机1台,GW48-PK2S实验箱1台,QuartusⅡ6.0 1套. 三.实验内容 1. 基本命题 利用图形输入法设计一个一位半加器和全加器,再利用级联方法构成8位加法器. 2. 扩展命题 利用文本输入法设计4位并行进位加法器,再利用层次设计方法构成8位加法器.通过时序仿真,比较两种加法器的性能. 四.实验设

实验二:SQL server 2005高可用性之----数据库镜像

如转载,请注明出处:http://blog.csdn.net/robinson_0612/archive/2009/11/04/4769060.aspx       SQL server 2005高可用性之数据库镜像,是SQL server 2005的新技术之一,是一种基于软件的高可用性解决方案,可以对不同服务器或同一服务器不同实例之间的数据库实验无数据延迟,自动故障转移的热备份.数据库镜像是基于数据库级别的,只适用于使用完整恢复模式的数据库.       一.实验目的:掌握SQL server

数据库表的查询操作(实验二)

[实验目的]:了解SQL语言的使用,进一步理解关系运算,巩固数据库的基础知识. [实验要求]:掌握利用Select语句进行各种查询操作:单表查询.多表连接及查询.嵌套查询.集合查询等. [实验内容] 一.单表查询 1.简单查询 打开查询分析器,根建立teacher表,并加入数据.从teacher表中分别检索出教师的所有信息,以及仅查询教工号.姓名和职称.语句如下: select * from teacher select tno, tname from teacher 如要查询时改变列标题的显示

数据库表的查询操作(实验二)_MsSql

[实验目的]:了解SQL语言的使用,进一步理解关系运算,巩固数据库的基础知识.[实验要求]:掌握利用Select语句进行各种查询操作:单表查询.多表连接及查询.嵌套查询.集合查询等.[实验内容]一.单表查询1.简单查询打开查询分析器,根建立teacher表,并加入数据.从teacher表中分别检索出教师的所有信息,以及仅查询教工号.姓名和职称.语句如下: select * from teacher select tno, tname from teacher 如要查询时改变列标题的显示,则从te

实验二 栈和队列的应用

实验目的 本次实验的目的在于使学生深入了解栈和队列的特征,掌握在实际问题背景下的灵活运用. 实验要求 正确设计和实现本程序,记录输出结果. 实验内容 1.队列的各种基本操作实现. 2.十进制数向N进制数据的转换.(栈的应用) 附:代码 #include <stdio.h> #include <string.h> #include <stdlib.h> #define OVERFLOW 0 #define OK 1 #define ERROR 0 //顺序栈的定义 #de

实验证明权重决定百度是否收录博客外链

长期以来利用博客做外链是众多新站长和SEOER们喜欢的方式之一.也是外链来的最快最好的方式之一,但是现在不一样了,众所周知,现在博客的权重已经远不如以前了,各大门户博客权重基本上都被降低,这导致很多seoer认为博客做外链成了食之无味弃之可惜的鸡肋,你还在利用博客做外链吗,新手站长和SEOER们? 对于博客是否真的成了食之无味弃之可惜的鸡肋的看法,甚至有很多的seoer认为博客外链已经完全失效了.我有不一样的看法,我觉得博客做外链的味道还是挺美味的,自从谷歌全面退出中国内地市场以后,百度SEO已

ORACEL空间管理实验(九)ORACEL空间管理汇总

索引和表的扫描/闪回时的块管理方式 1.补充--关于dba_objects中的 DATA_OBJECT_ID 和OBJECT_ID字段: truncate table test1; alter table test1 move tablespace tp2; select object_id,data_object_id from dba_objects where object_name='TEST1'; OBJECT_ID DATA_OBJECT_ID ---------- --------