算术表达式的求解-数据结构课程设计报告

1970-01-01 08:00

课程设计报告

题目:算术表达式求值 一、需求分析 1、设计要求:

给定一个算术表达式,通过程序求出最后的结果 1>、从键盘输入要求解的算术表达式; 2>、采用栈结构进行算术表达式的求解过程; 3>、能够判断算术表达式正确与否; 4>、对于错误表达式给出提示;

5>、对于正确的表达式给出最后的结果; 2、设计构想:

为了实现算符优先算法使用两个工作栈,一个称作OPTR,以寄存运算符;另一个称作OPND,用以寄存操作数或运算结果。在操作数和操作符入栈前,通过一个函数来判别,输入的是操作数还是操作符,操作数入OPND,操作符入OPTR。在输入表达式的最后输入‘#’,设定‘#’的优先级最低,代表表达式输入结束。在表达式输入过程中,遇操作数则直接入栈,遇到运算符则与栈顶运算符比较优先级,若当前运算符优先级高,则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,两操作数出栈,进行运算,所得结果入数栈,重新比较当前运算符与新栈顶运算符。如此重复直到栈顶运算符与当前符号均为‘#’,运算结束。 二、概要设计

1、本程序包含的模块:

(1)栈模块——实现栈抽象数据类型 (2)运算模块——实现数据表达式的运算 (3)主程序模块

算术运算式的求解 栈模块 主函数模块main 运算模块 定义栈结构 初始化栈 出栈 入栈 取栈顶元素 判断输入字符类型 判断符号优先级 基础运算函数 运算函数 三、详细设计 (1)栈模块

1、定义栈结构 struct Sqstack

{

elemtype *top;//栈顶元素 elemtype *base; //栈底元素 int stacksize;//栈的大小 };

2、栈的基本操作 ①初始化栈

status initstack(struct Sqstack &s) {

s.base=(elemtype *)malloc(stack_size*sizeof(elemtype)); if(!s.base) return OVERFLOW; s.top=s.base;

s.stacksize=stack_size; return OK; } ②入栈

status push(struct Sqstack &s,elemtype e) {

if(s.top-s.base>=s.stacksize) {

s.base=(elemtype*)realloc(s.base,(s.stacksize+stack_increase

ment)*sizeof(elemtype));

if(!(s.base)) return OVERFLOW; s.top=s.base+s.stacksize; s.stacksize+=stack_increasement; }

* s.top++=e; return OK; } ③出栈

elemtype pop(struct Sqstack &s) {

elemtype e; if(s.top= =s.base) return ERROR; e=*--s.top;

return e; }

④取栈顶元素

elemtype gettop(struct Sqstack &s) {

elemtype e; if(s.top==s.base) return ERROR; e=*(s.top-1); return e; }

(2)运算模块

1、判断输入字符c是否为操作符:若是,则返回1;否则,返回0 int In(int c) {

char p[10]=\ int i=0;

while(p[i]!='\\0') {

if(p[i]==c) return 1;

i++; } return 0; }

2、判断运算符的优先级

char precede(char top,char c)

//该函数为判断当前运算符与前一个运算符的优先级,前一个运算符高于或等于当前运算符的优先级则返回‘>’, 前一个运算符小于当前运算符的优先级则返‘<’,当前一个运算符为‘(’当前运算符为‘)’时返回‘=’,用于去除表达式的括号。

{

char result; switch(c) {

case '#': result='>'; break; case '+': case '-':

if(top=='#'||top=='(')

result='<'; else

result='>'; break; case '*': case '/':

if(top=='*'||top=='/'||top=='^') result='>'; else

result='<'; break; case '%':

if(top=='%'||top=='/'||top=='^'||top=='*') result='>'; else

result='<';break; case ')': if(top=='(') result='='; else

result='>'; break;

case '(': result='<'; break; case '^': result='<'; break;

default: printf(\操作符输入错误!\\n\ }

return result; }

3、运算函数 ① 基础运算函数:

实现相应的加、减、乘、除、乘方及带小括号的基本数学运算并返回结果,其中a,b为两个操作数,theta为操作符

elemtype operate(elemtype a,char theta,elemtype b) {

elemtype result; switch(theta) {

case '+': result=a+b; break; case '-': result=a-b; break; case '*': result=a*b; break; case '/':

if(b==0)

{

printf(\输入错误!分母不能为0!\\n\ result=0;

}

else

result=a/b;break; case '%':

if(b==0||b==NULL)

{ } else

printf(\输入错误!\\n\return 0;break;

result=a%b;break;

case '^': result=(int)pow((double)a,(double)b); break; default: printf(\操作符输入错误!\\n\ }

return result;

} ②运算函数

elemtype evaluate(struct Sqstack opnd,struct Sqstack optr) //该函数为求表达式的值的整个操作过程,通过调用相应的函数实现遇到运算符则与栈顶运算符比较优先级,

//若当前运算符优先级高(前面的运算还不应执行)则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,同时两操作数出栈,进行运算,所得结果入数栈,

//重新比较当前运算符(注意当前运算符未变)与新栈顶运算符。如此重复直到栈顶运算符与当前符号均为‘#’,运算结束。

//若操作数为个位数,则直接将输入的字符减48后入栈,若为多位数,则通过flag来实现。若输入字符c为操作数且flag=1(即操作数为多位数),则将操作数栈的栈顶元素出栈后乘以10,然后加上,(c-48)然后将二者的和入操作数栈。

{

elemtype a,b,c,theta,e; initstack(optr); push(optr,'#'); initstack(opnd); c=getchar(); int flag=0;

//当输入操作数时flag=1;当输入操作符时flag=0;

//当前输入为操作数且flag=1时,将操作数栈的栈顶元素出栈,然后将其和当前输入转换成相应的int类型

while(c!='#'||gettop(optr)!='#') {

if(!In(c)) //c若为操作数则入opnd栈

{

if(flag==1)

{

e=pop(opnd); // 取栈顶元素 push(opnd,(e*10+(c-48)));

//将输入数在转化为int型,并将上次输入数*10并与当前操作数相加,将结果如操作数栈

}

else

push(opnd,c-48); flag=1; c=getchar();

}

else

{

flag=0;

//当前字符为操作符,则入操作符栈,并将flag置为0 switch(precede(gettop(optr),c))

// 判断当前操作数与操作符栈中的栈顶元素的优先级

{

case '<': push(optr,c); c=getchar(); break;

// 若当前操作符的优先级高于操作符栈的栈顶元素,则将当前操作符入操作符栈

case '=': e=pop(optr); c=getchar(); break;

// 若当前操作符与操作符栈的栈顶元素构成匹配的括号,则//将操作符栈顶元素出栈

case '>': theta=pop(optr); b=pop(opnd); a=pop(opnd); push(opnd,operate(a,theta,b)); break;

// 若当前操作符的优先级低于操作符栈的栈顶元素,则将操作符栈栈顶元素出栈,并将操作数栈的栈顶两个元素出栈,计算两个元素间以操作符栈栈顶元素为运算符的数学运算

}//switch }//if

}//while

return pop(opnd); }

(3)主程序模块

1、main函数

void main(int argc,char *argv[]) {

struct Sqstack opnd; //操作数栈 struct Sqstack optr;//操作符栈 initstack(opdn); initstack(optr); elemtype result;

printf(\ printf(\算术运算式的求解\

printf(\ printf(\请输入算术运算表达式(以'#'结尾):\\n\ printf(\

result=evaluate(opnd,optr);

printf(\

printf(\运算的结果是 :\\n \\n%d\\n\

printf(\}

四、调试分析 1、测试结果

1> 测试数据:3+7*2-1# 测试结果:

2> 测试数据:(3+7)*2-1# 测试结果:

3> 测试数据: 1/0# 测试结果:

2、程序时间复杂度为O(n); 3、设计中出现的问题:

在开始的设计中没有注意除数不能为0 ,后来加入

if(b==0) {

printf(\分母为0,the result is error\\n\ result=0; } else

result=a/b;break;来判断除数是否为0 4、算法改进:

1>输入的操作数和操作码由于是字符串类型的,在原设计中实现的操作都是对个位数实现的,实用性不大,故在后来的设计中,通过一个标志flag实现了标志操作数的连续输入的判别,继而实现了多位数的表达式运算

2>开始只实现了加、减、乘、除及带小括号的数学运算,考虑到实用性,在后来的设计中引入pow函数,实现了乘方的运算,调整结果如下:

3>最初设计的运行界面过于单调,不够友好,改进时加入一些*调整 调整结果如下:

五、课程设计总结

本学期是我第一次接触课程设计,发现了很多学习上的问题,也有很多收获。

在这两周的时间里,我再一次复习并更深入的了解了数据结构及C语言之中的相关知识,通过《算术运算式的求解》这一题目,形象深入的理解了栈结构及

原理。同时,通过每一次的编译运行不断改进完善题目,并通过这一个不断改进的过程,完善自己的思想,增强了自己全面分析问题的能力。

当然,第一次的课程设计我做的还不够好,还有很多不足,缺少实践,缺乏经验,但我相信,在今后的设计中,我会加倍努力,珍惜机会,将所学知识融会贯通并与实际相结合


算术表达式的求解-数据结构课程设计报告.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:电工技术题库

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: