表达式求值课程设计报告文档格式.docx

上传人:b****7 文档编号:22408622 上传时间:2023-02-03 格式:DOCX 页数:19 大小:116.64KB
下载 相关 举报
表达式求值课程设计报告文档格式.docx_第1页
第1页 / 共19页
表达式求值课程设计报告文档格式.docx_第2页
第2页 / 共19页
表达式求值课程设计报告文档格式.docx_第3页
第3页 / 共19页
表达式求值课程设计报告文档格式.docx_第4页
第4页 / 共19页
表达式求值课程设计报告文档格式.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

表达式求值课程设计报告文档格式.docx

《表达式求值课程设计报告文档格式.docx》由会员分享,可在线阅读,更多相关《表达式求值课程设计报告文档格式.docx(19页珍藏版)》请在冰豆网上搜索。

表达式求值课程设计报告文档格式.docx

运算先乘除,后加减;

同级运算从左到右。

如下表达式:

50+(6*3+2)

要求:

(1)用C/C++语言编写一个程序将这组学生成绩输入到计算机中,数据运算的存储逻辑结构为栈。

(2)程序要能正确处理表达式的优先级、输出正确运算结果。

最终设计成果形式为:

1、设计好的软件一套;

2、撰写一份课程设计说明书一份,打印并装订成册。

指导教师(签字):

教研室主任(签字):

批准日期:

1课题描述…………………………………………………………………………………………1

2设计思路…………………………………………………………………………………………2

3算法设计…………………………………………………………………………………………3

4程序代码…………………………………………………………………………………………5

5测试及分析……………………………………………………………………………………..12

6总结……………………………………………………………………………………………..13

参考文献…………………………………………………………………………………………..13

1课题描述

表达式求值是程序设计语言编译中的一个最基本问题。

表达式求值在计算机中的实现是栈结构在计算机中的一个典型应用。

这里使用“算符优先算法”实现表达式求值。

要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值,首先要能够正确解释表达式。

例如对表达式求值:

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

即:

先算括号内,后算括号外;

先乘除后加减;

同级运算顺序从左到右;

所以,这个表达式的运算顺序为:

50+(6*3+2)=50+(18+2)=50+20=70

算符优先算法就是根据这个运算优先关系来编译或者解释执行的。

2设计思路

2.1表达式的输入:

表达式从键盘输入,存入字符串数组中。

2.2运算的实现:

任何一个表达式都是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。

可以把运算符和界限符统称为算符,根据算术运算规则,在运算的每一步中,任意两个相继出现的算符opt1和opt2之间的优先关系至多是下面三种关系之一:

opt1<

opt2,即opt1的优先级低于opt2;

opt1=opt2,即opt1的优先级等于opt2;

opt1>

opt2,即opt1的优先级高于opt2。

表1定义了算符间的优先关系:

Opt2

Opt1

+

-

*

/

#

>

<

=

NULL

表1

输入的表达式(包含运算符和操作数)以字符串的形式输入,故需要一个字符串数组存储键盘的输入。

在对输入的表达式求值前,应先检查输入的合法性。

只有正确的输入才能输出正确的计算结果。

算符优先算法运算需要两个栈:

操作数栈(OPND)和运算符栈(OPTR)。

栈可以采用数组实现,并定义栈的相关操作:

初始化、压栈、出栈、判断栈满、判断栈空等相关操作。

输入的字符串解析分离出操作数和运算符,分别进入操作数栈和运算符栈。

运算始终在栈顶实现,最终操作数栈只剩一个元素,即运算结果。

3算法设计

使用两个工作栈:

一个称作OPTR,用以寄存运算符;

另一个称作OPTD,用以寄存操作数或运算结果。

算法的基本思想是:

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

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

算法如下:

OperandTypeEvaluateExpression(){

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

OPTR和OPND分别为运算符栈和运算数栈

//OP为运算符集合{+、-、*、/、(、)、#、.}

InitStack(OPTR);

Push(OPTR,‘#’);

InitStack(OPND);

c=getchar();

while(c!

=’#’||GetTop(OPTR)!

=’#’){

if(!

IsOpt(c)){Push(OPND,c);

}//不是运算符则进栈;

else{

switch(Precede(GetTop(OPTR),c)){

case‘<

’:

//栈顶元素优先级低

Push(OPTR,c);

break;

case‘=’:

//脱括号并接收下一字符

Pop(OPTR,x);

case‘>

//退栈并将运算结果入栈

Pop(OPTR,theta);

Pop(OPND,b);

Pop(OPND,a);

Push(OPND,Operate(a,theta,b));

}//switch

}//while

ReturnGetTop(OPND);

}//EvaluateExpression

算法中还调用了两个函数。

其中Precede是判定运算符栈的栈顶运算符opt1与读入的运算符opt2之间优先关系的函数;

Operate为进行二元运算aoptb的函数,如果是编译表达式,则产生这个运算的一组相应指令并返回存放结果的中间变量名;

如果是解释执行表达式,则直接进行该运算,并返回运算的结果。

程序流程图如下:

4程序代码

#if0

/*

2015年9月8日09:

10:

14

表达式求值算法——算符优先算法的实现

*/

#endif

#defineDebuging0//当值为一时,开启调试

#include<

stdio.h>

stdlib.h>

string.h>

#defineOVERFLOW-2

#defineERROR0

#defineINFEASIBLE-1

#defineOK1

#defineTRUE1

#defineFALSE0

#defineOPERANDdouble

#defineOPERATORchar

#defineSTACK_INIT_SIZE100

#defineSTACKINCREMENT10

#defineMAX_QUEUE_SIZE100

#defineOPERATORNUM8//操作符的数量

typedefstruct{

/*定义操作数栈*/

OPERAND*base;

OPERAND*top;

intiStackSize;

}OPNDStack,*pOPNDStack;

/*定义运算符栈*/

OPERATOR*base;

OPERATOR*top;

}OPTRStack,*pOPTRStack;

charcOpt[]={'

+'

'

-'

*'

/'

('

)'

#'

.'

};

charcPriority[7][7]={

{'

'

},

='

NULL},

NULL,'

}

intInitOPNDStack(pOPNDStackS);

OPERANDGetOPNDTop(pOPNDStackS);

intPushOPND(pOPNDStack,OPERANDe);

intPopOPND(pOPNDStackS,OPERAND*e);

intInitOPTRStack(pOPTRStackS);

OPERATORGetOPTRTop(pOPTRStackS);

intPushOPTR(pOPTRStackS,OPERATORe);

intPopOPTR(pOPTRStackS,OPERATOR*e);

OPERANDOperate(OPERANDfOperandA,OPERATORcOperator,OPERANDfOperandB);

OPERANDEvaluateExpression(char*Expression);

intWhichOptNum(charopt);

intIsOpt(charopt);

intCheckExpression(char*Expression);

intmain(void){

//表达式求值——算符优先算法

OPERANDe=0.0;

charExpression[50]="

"

;

system("

colorf0"

);

while(OK)

{

fflush(stdin);

printf("

输入表达式:

"

gets(Expression);

strcat(Expression,"

#"

//printf("

%s"

cPriority);

if(CheckExpression(Expression)){

e=EvaluateExpression(Expression);

printf("

Answer=%f\n"

e);

}

else{

输入中缀表达式有误!

\n"

continue;

}

}

return0;

}//main

intInitOPNDStack(pOPNDStackS){

//构造一个空栈,栈内数据类型为OPND(浮点数据)

S->

base=(OPERAND*)malloc(STACK_INIT_SIZE*sizeof(OPERAND));

S->

base)

exit(OVERFLOW);

//这么写错误处理显然还不成熟

top=S->

base;

iStackSize=STACK_INIT_SIZE;

returnOK;

}//InitOPNDStack

OPERANDGetOPNDTop(pOPNDStackS){

//读取栈顶元素,不删除栈顶元素

if(S->

top==S->

//栈空

return*(S->

top-1);

}//GetOPNDTop

intPushOPND(pOPNDStackS,OPERANDe){

//将新的OPND元素入栈,栈满则增加空间

top-S->

base>

=S->

iStackSize){

S->

base=(OPERAND*)realloc(S->

base,\

(S->

iStackSize+STACKINCREMENT)*sizeof(OPERAND));

if(!

exit(OVERFLOW);

//空间不够了

base+S->

iStackSize;

iStackSize+=STACKINCREMENT;

#ifDebuging

增加OPND空间辣!

system("

pause"

}//if

*(S->

top++)=e;

}//PushOPND

intPopOPND(pOPNDStackS,OPERAND*e){

//若栈不空,删除S栈顶元素,并用e返回其值

returnERROR;

*e=*(--S->

top);

}//PopOPND

intInitOPTRStack(pOPTRStackS){

//构造一个空栈,栈内数据类型为OPTR

base=(OPERATOR*)malloc(STACK_INIT_SIZE*sizeof(OPERATOR));

}//InitOPTRStack

OPERATORGetOPTRTop(pOPTRStackS){

//栈空

}//GetOPTRTop//哎。

重复造轮子

intPushOPTR(pOPTRStackS,OPERATORe){

//将新的OPTR元素入栈,栈满则增加空间

base=(OPERATOR*)realloc(S->

iStackSize+STACKINCREMENT)*sizeof(OPERATOR));

//空间不够

增加OPTR空间辣!

}//PshOPTR

intPopOPTR(pOPTRStackS,OPERATOR*e){

}//PopOPTR

OPERANDOperate(OPERANDfOperandA,OPERATORcOperator,OPERANDfOperandB){

//将操作数计算后返回

switch(cOperator)

case'

:

return(fOperandA+fOperandB);

break;

return(fOperandA-fOperandB);

return(fOperandA*fOperandB);

return(fOperandA/fOperandB);

default:

运算出了BUG。

中彩蛋了。

}//Operate

OPERANDEvaluateExpression(char*Expression){

//算符优先算法

OPNDStackNumStack;

OPTRStackOptStack;

charc='

'

inti=0;

OPERATORopt=0;

OPERANDtmp=0.0,fTmp=0.0,iTmp,j=0.0,fOperandB,fOperandA;

InitOPNDStack(&

NumStack);

InitOPTRStack(&

OptStack);

PushOPTR(&

OptStack,'

c=Expression[i++];

while(c!

='

||GetOPTRTop(&

OptStack)!

){

IsOpt(c)){

fTmp=0.0;

iTmp=c-'

0'

c=Expression[i++];

while(!

iTmp=iTmp*10+c-'

c=Expression[i++];

}

if(c=='

for(j=0.1;

!

IsOpt(c);

j*=0.1){

fTmp+=j*(c-'

c=Expression[i++];

}

//这里不需要了else

tmp=iTmp+fTmp;

PushOPND(&

NumStack,tmp);

else

switch(cPriority[WhichOptNum(GetOPTRTop(&

OptStack))][WhichOptNum(c)])

{

case'

PushOPTR(&

OptStack,c);

break;

PopOPTR(&

OptStack,&

c);

//脱括号接收下一字符

opt);

PopOPND(&

NumStack,&

fOperandB);

fOperandA);

PushOPND(&

NumStack,Operate(fOperandA,opt,fOperandB));

}//switch

tmp=GetOPNDTop(&

free(NumStack.base);

free(OptStack.base);

returntmp;

intWhichOptNum(charopt){

//检测操作符所在的位置

for(i=0;

i<

OPERATORNUM;

++i){

if(cOpt[i]==opt){

returni;

}//WhichOptNum

intIsOpt(charopt){

//判断是不是操作符

if(opt==cOpt[i])

returnTRUE;

returnERROR;

}//IsOpt

intCheckExpression(char*Expression){

//检查输入的合法性,合法返回1,否则返回0;

while(Expression[i]){

if((Expression[i]>

&

&

Expression[i]<

9'

)||IsOpt(Expression[i])){

if(IsOpt(Expression[i])&

IsOpt(Expression[i+1])\

(Expression[i]!

Expression[i+1]!

))

return0;

else{

++i;

continue;

return0;

Expression[i])

return1;

}//CheckExpression

5测试及分析

在数据范围不溢出的情况下本设计仅可能出现两种情况:

(1)输入正确的中缀表达式,输出正确的计算结果。

(2)输入错误的中缀表达式,报告输入错误并要求重新输入。

表5.1设计的试验结果:

输入

输出

(1)输入正确

70

5+5+5+5+5+5+5

35

4.5*3-(1+2)/1

10.5

(2)输入错误

6++8

“输入中缀表达式有误”

3++dh

“输入中缀表

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 院校资料

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1