山东科技大学电子商务10-1 算术表达式报告_第1页
山东科技大学电子商务10-1 算术表达式报告_第2页
山东科技大学电子商务10-1 算术表达式报告_第3页
山东科技大学电子商务10-1 算术表达式报告_第4页
山东科技大学电子商务10-1 算术表达式报告_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、数数 据据 结结 构构 课课程程设设计计 报报告告 设计题目: 算术表达式 院 系: 经济管理学院 专业班级: 电子商务 2010-1 学生姓名: 孙建、王斌、王文崇 指导教师: 周长虹 2012 年 7 月 6 日 指导教师评语 指导教师: 年 月 日 成绩评定 学 号姓 名任务分工成绩 孙建搜集资料,撰写报告 目目 录录 1.设计内容设计内容 .1 1.1 问题描述.1 1.2 设计要求.1 1.3 开发环境.1 1.4 研究思路.1 2.设计步骤设计步骤 .1 2.1 需求分析.1 2.2 概要设计.2 2.3 详细设计.3 2.4 调试分析.3 2.5 测试结果.4 3.设计成果展示设

2、计成果展示 .7 3.1 用户手册.7 3.2 程序运行部分截图.7 4.总结与心得体会总结与心得体会 .8 附附 录录 .9 1.设计内容设计内容 1.1 问题描述问题描述 问题描述:当用户输入一个合法的算术表达式后,能够返回正确的结果。 能够计算的运算符包括:加、减、乘、除、括号;能够计算的操作数要求 在是属于范围内;对于一场表达式能够给出错误提示。 1.2 设计要求设计要求 要求:(1)从键盘输入一个表达式; (2)支持运算符的优先级; (3)支持括号的嵌套; (4)支持小数点及其负数; (5)有差错功能,如非法字符,小数点过多(3.44.3) ,括号不匹 配等错误。 1.3 开发环境开

3、发环境 C-free 5.0 1.4 研究思路研究思路 当用户输入一个算法表达式,程序在只将表达式扫描一遍的条件下, 运用一个能提取出一个数据项和一个符号项的函数,通过循环调用这个函 数,并利用栈操作函数,实现对表达式的计算.对括号匹配的处理是用一个 计数器变量,出现左括号加 1,出现右括号减 1,值为 0 说明括号匹配. 2.设计步骤设计步骤 2.1 需求分析需求分析 该程序的主要任务是,当用户输入一个算术表达式的时,该程序能计算出 输入表达式的结果;如果输入的表达式有误(字符错误和逻辑错误) ,该 程序能输出算术表达式的具体错误形式。难点在于运算符、括号与数字的 出入栈操作。 输入形式:由

4、用户输入一个用户认为合法并且合乎逻辑的算术表达式 (输入的算数表达式并不一定正确) 。 输出形式:1、用户输入的算数表达式合法且合乎逻辑,则在用户界面 上输出该算数表达式的结果;2、用户输入的算术表达式有语法错误或者 不合乎逻辑,则在用户界面上输出算术表达式出错及其具体错误。 该程序所能达到的功能为:在用户输入一个合法且误逻辑语法错误的 算术表达式时,能给出相应的算术表达式计算结果;在输入的表达式有误 时,能给出具体的错误类型,以方便修改。 2.2 概要设计概要设计 (1)根据设计思路,首先是对整个程序中变量的定义,其中大致包括: #define MAX_DATA_BIT 100 #defin

5、e YES 1 #define NO 0 #define POINT_UNEXIST -15 #define MAXSIZE 100 (2) 对内容的设计,其中各主要过程的函数包括 函数 getexp 这个函数的原型是:int getexp(double *data,char *); 它能够提取 出表达式中的数据项和符号项,对这个函数的调用,至少能提取出一个符号 项, 根据提取的项不同,其返回值从 1 到 8 有个;返回负数表示在提取的过 程中有错误;对负数的处理是;除了第一项的负数外,其它的负数必须用括 号括起来; 函数 PopData , PushData , PopOprt ,PushO

6、prt 这四个函数分别实现数据入栈出栈,操作符入栈出栈; 函数 calculat 原型是: int calculat(double data1,char oprt,double data2);能 对两个数据根据 oprt 进行计算,计算出现错误返回负数,否则返回正数; 函数 checkgram 原型是:int checkgram(int fsitua,int lsitua);配合 getexp 的 返回值使用,对表达式进行语法检查; 函数 priority 原型是:int priority(char cal1,char cal2);比较操作符的优先 级,为了保持一致性,把0和括号也看作操作符;

7、 函数 char_to_double 原型:double char_to_double(char DigitString,int markpot,int markend);将字符串转变成双精度数; 函数 main 主函数:(1)调用函数 clear()清空栈; (2)调用函数 getxp()提取字符; (3)调用函数 checkgram()判断字符是否合法; (4)调用函数 priority()判断运算符的优先级; (5)调用函数 calculat()计算算术表达式; (6)如果以上均未出现错误,输出算术表达式的计算结果;如果任 意一步出现错误,调用函数 error()输出错误类型。 2.3

8、详细设计详细设计 对子函数进行声明部分: int is_calchar(char c); /标识运算符,不包括括号 int is_space(char c); /标识空白字符,不包括换行符 int is_FIRST_allow(char c); /标识表达式第一个合法字符 int is_allowed(char c); /标识表达式的合法字符 double char_to_double(char DigitString,int markpot,int markend); /函数, 将字符串转换成双精度数 int get_exp(double *data,char *oprt); /得到表达式的

9、项,并检查字符是否 合法 typedef struct char oprt_stackMAXSIZE; double data_stackMAXSIZE; char oprt_in,oprt_out,*oprt_curp; double data_in,data_out,*data_curp; stack;/关于堆栈的相关操作及声明 int PopData(stack *p);/数字的入栈 int PushData(stack *p);/数字的出栈 int PopOprt(stack *p);/操作符的入栈 int PushOprt(stack *p);/操作符的出栈 void clear(s

10、tack *p);/清空栈 int check_grammer(int fsitua,int lsitua); /语法检查函数,返回 2 表示表达 式结束 int priority(char cal1,char cal2); /功能函数,比较两个运算符的优先级 void error(int state); /错误处理函数,丢弃出错后所有字符,并打印出错信 息 int calculat(double data1,char oprt,double data2,double *result); /计算函数,有 发现简单逻辑错误的功能 stack STK;/创建堆栈; 对整个程序的编写,是从一个子函数

11、 isoprt()的编写开始的。 int isoprt( char c)/判断是不是运算符 if (c=+|c=-|c=*|c=/) return 1; else return 0; /如果是+、-、*、/四种运算符则返回真值,如果不是则返回假值。 int is_space(char c)/判断是不是空格; if (c= |c=t|c=v) return 1; else return 0; /如果是空格,则返回真值,如果不是,则返回假值。 int is_FIRST_allow(char c)/判断表达式开头是否合法; if (c=.|c=-|c=(|isdigit(c) return 1; e

12、lse return 0; /如果开头是数字、小数点、负号、左括号则返回真值,否则返回假 值。 int is_allowed(char c)/判断字符是否合法; if (c=.|isoprt(c)|c=(|isdigit(c)|c=) return 1; else return 0; /如果是运算符或者小数点、左右括号、负号、数字则返回真值,否 则返回假值。 double char_to_double(char data,int markpot,int markend)/单精度转 换为双精度; int i; double sumz=0,sumf=0; if (data0!=-) for (i=

13、0;imarkpot;-i) sumf=sumf*0.1+(datai-0); return sumz+sumf*0.1; else for (i=1;imarkpot;-i) sumf=sumf*0.1+(datai-0); return -(sumz+sumf*0.1); /将字符转化为双精度数。 函数 getexp()是整个程序中最核心的部分,它的功能是提取出表达 式中的数据项和符号项,被主函数和几乎所有子函数所调用。每次提取出 一个项,根据提取的符号项不同,其返回值从 1 到 8 各有不同;返回负数表 示在提取的过程中有错误;该函数对于负号的处理是;除了第一项的负数外, 其它的负数必须

14、用括号括起来。 int get_exp (double *data,char *oprt) c=getchar( );/c 是从输入的算术表达式中取值; if ( isoprt(c) ) return 1; /如果是运算符,则返回 1; if( c=() BRACKET_COUNT+;return 2; /如果是左括号,则返回 2; if( c=) BRACKET_COUNT-; return 3; /如果是右括号,则返回 3; if( c=n) return4; /如果是换行,则返回 4; if ( isoprt(c) ) *oprt=c, return 5; /如果是运算符,将 c 的值赋

15、给特殊运 算符,返回 5; if( c=() *oprt=c, BRACKET_COUNT+;return 6; /如果是左括号, 将 c 的值赋给特殊运算符,返回 6; if( c=) *oprt=c, BRACKET_COUNT-; return 7; /如果是右括号, 将 c 的值赋给特殊运算符,返回 7; if( c=n) *oprt=c, return 8; /如果是换行,将 c 的值赋给特殊运算符, 返回 8; if (!is_allowed(c) return -1;/如果不是合法字符,返回-1; if(!is_FIRST_allow(c) return -4;/如果表达式开头不

16、合法,返回-4; if(i=MAX_DATA_BIT/如果数字超多最大值, 返回-3; if (c=./如果小数点错误, 返回-2; if ( BRACKET_COUNT!=0 ) return-6;/在此说明 BRACKET_COUNT 是括号的计数器,出现左括号,BRACKET_COUNT 就加一;出现右括号 BRACKET_COUNT 就减一,直至最后 BRACKET_COUNT 不为零,则说 明左右括号不匹配。 int priority (char cal1,char cal2)/判断运算符的优先级; if(cal1=0|cal1=(|cal2=(|cal2=|(cal2=*|cal2

17、=/)/如果前一个运算符的的优先级高于后一个运算符, 则返回-1 else return 1;/否则,返回 1 / int check_grammer (int fsitua,int lsitua) /检查语法 switch (fsitua) case 1:case 5:if (lsitua=1|lsitua=2|lsitua=3|lsitua=4|lsitua=6) return 1; else return -4;/如果前者为运算符,后者就不能是右括 号、运算符、换行;符合返回 1,不符合返回-4; case 2: case 6:if (lsitua=1|lsitua=2|lsitua=3

18、|lsitua=6) return 1; else return -4;/如果前者是左括号,后者就不能是运算 符、右括号、换行;符合返回 1,不符合返回-4; case 3: case 7:if (lsitua=5|lsitua=6|lsitua=7|lsitua=8) return 1; else return -4;/如果前者是右括号,后者就不能是数字; 符合返回 1,不符合返回-4 default:return 1; /以上数字都是由 get_exp( )函数中获得的返回值; int PopData(stack *p)/数字入栈; if (p-data_curp = p-data_sta

19、ck) return -1; else p-data_out = *p-data_curp; *p-data_curp=0; p-data_curp-; return 1; int PushData(stack *p)/数字出栈; if (p-data_curp=p-data_stack+MAXSIZE-1) return -1; else p-data_curp+; *p-data_curp=p-data_in; return 1; int PopOprt(stack *p)/操作符入栈; if (p-oprt_curp = p-oprt_stack) return -1; else p-o

20、prt_out = *p-oprt_curp; *p-oprt_curp = 0; p-oprt_curp -; return 1; int PushOprt(stack *p)/操作符出栈; if (p-oprt_curp = p-oprt_stack + MAXSIZE-1) return -1; else p-oprt_curp +; *p-oprt_curp = p-oprt_in; return 1; void clear(stack *p)/清空前一次运算所用的堆栈; while(p-data_curp != p-data_stack) *(p-data_curp-) = 0; w

21、hile(p-oprt_curp != p-oprt_stack) *(p-oprt_curp-) = 0; void error (int state)/错误提示函数; if (state=-1) printf(n 表达式出现不合法字符!n); else if(state=-2) printf(n 表达式有不合法数据项!n); else if(state=-3) printf(n 表达式中数据太大了!n); else if(state=-4) printf(n 表达式有语法错误!n); else if(state=-5) printf(n 表达式逻辑错误nn 除数不能为 0!n); else

22、 if(state=-6) printf(n 表达式的括号不匹配!n); /以上 state 为字符提取函数、语法检验函数、计算函数的返回值。 int calculat (double data1,char calchar,double data2,double *result) switch(calchar) case +:*result=data1+data2;return 1; case -:*result=data1-data2;return 1; case *:*result=data1*data2;return 1; case /:if (data2!=0.0) *result=d

23、ata1/data2;return 1; else return -5;/如果被除数是 0,则返回值是-5;即被除 数不能为 0; void main( )/主函数部分; clear(/获得算术表达式;/ if ( state0 ) *STK.oprt_curp=(; PopPort( x ); PushPort( y );/前一个运算符优先级低于后一个运算符,将前一个 运算符入栈,后一个运算符出栈; Calculat( );/计算已经由中缀表达式转换为后缀表达式的算术表达 式; Printf(“运算结果”);/输出运算结果; 主函数的运算过程:通过调用 clear()函数对栈进行清空,get

24、exp()函 数提取出表达式中的数据项和符号项,checkgram()函数对表达式进行语法 检查,如果出现错误就调用 error( )报错;如果正确继续进行,calculat( )函 数对表达式进行计算,并输出结果。ch 是运算符(含左右括号) ,则:a: 如果 ch = (,放入堆栈。b:如果 ch = ),依次输出堆栈中的运算符,直 到遇到(为止。c:如果 ch 不是)或者(,那么就和堆栈顶点位置的运算 符 top 做优先级比较。1:如果 ch 优先级比 top 高,那么将 ch 放入堆栈。 2:如果 ch 优先级低于或者等于 top,那么输出 top,然后将 ch 放入堆栈。 如果表达式

25、已经读取完成,而堆栈中还有运算符时,依次由顶端输出。 函数调用关系图: 程序流程图: 开始开始 isoprt 运算符运算符 is_space 空格空格 is_FIRST_allow 表达式首项合法表达式首项合法 is_allowed 合法字符合法字符 char_to_double 单精度转双精度单精度转双精度 get_exp 取项取项 Priority 优先级判断优先级判断 check_grammer 语法判断语法判断 PopData 数字入栈数字入栈 PopPort 操作符入栈操作符入栈 PushData 数字出栈数字出栈 PushPort 操作符出栈操作符出栈 clear 清空栈清空栈 e

26、rror 错误类型错误类型 calculate 计算计算 Main 主函数主函数 N Y N Y N Y 2.4 调试分析调试分析 调试过程: 我们遇到的问题是用户输入错误如何提示,我们开始着手时是用以下 判断语句 建立堆栈建立堆栈 清空栈清空栈 输入表达式输入表达式 提取字符提取字符 为合法字符为合法字符 操作符优先级判断操作符优先级判断 计算表达式计算表达式 无逻辑错误无逻辑错误 输出结果输出结果 输出错误类型输出错误类型 无语法错误无语法错误 if (state=-1) printf(表达式出现不合法字符!n); else if(state=-2) printf(表达式有不合法数据项!n

27、); else if(state=-3) printf(表达式中数据太大了!n); else if(state=-4) printf(表达式有语法错误!n); else if(state=-5) printf(表达式逻辑错误n 除数不能为 0!n); else if(state=-6) printf(表达式逻辑错误n 幂运算错误!n); else if(state=-7) printf(栈操作失败,表达式可能太长!n); else if(state=-8) printf(表达式的括号不匹配!); 来处理其中的问题。 2.5 测试结果测试结果 当用户输入错误算术表达式时能给出错误提醒。 如输入小

28、数点过多,缺少小括号等等。 3.设计成果展示设计成果展示 3.1 用户手册用户手册 此程序功能为计算简单算术表达式。 在运行程序之后,窗体内会显示简单的操作提示,根据提示进行相关 的操作。 首先运行程序,在程序启动后,根据提示输入算数表达式。如果算数 表达式正确,将在下方输出算数表达式结果;如果算数表达式错误,将在 下方输出算数表达式的具体错误。 程序使用流程图: Y N Y N 开始运行程序开始运行程序 阅读使用说明阅读使用说明 根据提示输入算术表达式根据提示输入算术表达式 表达式正确表达式正确 输出算术表达式计算结果输出算术表达式计算结果输出具体错误类型输出具体错误类型 继续运行继续运行

29、关闭程序关闭程序 3.2 程序运行部分截图程序运行部分截图 4.总结与心得体会总结与心得体会 当我们抽到题时我们立即开始了课程设计的准备工作搜索资料等。晚 上我们团队小组开会,统筹运作,制定课程设计计划,分配各人的具体任 务,然后执行计划。当然设计过程并非想象中那么一帆风顺,完成作品也 绝非纸上谈兵就可以。实践过程中各种问题不断出现,有过过失甚至矛盾, 但是作为一个团队我们在困难面前没有屈服。在团队合作的精神指导下, 我们再次召开小组会议,及时彼此沟通、交流思想,总结工作成果、分析 进展及待完成的任务、检讨不足之处加以改进。虽然过程中屡屡受挫,耐 心和激情也被程序调试打磨的所剩无几,一度失落。

30、但我们不是孤立无援 的,队友是我们最好的合作伙伴,是彼此之间的精神支柱。在相互鼓励、 共同努力之下,我们终于完成了课程设计,虽然我们做的并不优秀,但是 作品是我们团队合作共同努力的结晶,我们依然自豪。通过这次的课程设 计,我们从中收获颇多。设计过程我们将理论知识切实的应用于实践操作 中,实现了理论与实践的结合,提高了实践动手能力,加强了对实际问题 的分析、思考及解决能力。结果重要,但是经历的过程更重要。我们收获 的不仅是成果的成就感和知识上的巩固提升,更重要的是从课程设计中感 悟的经验,学到的团队合作精神、越挫越勇的斗志以及做任何事都要谨慎 认真踏实努力的教训。团队需要个人,个人也离不开团队,

31、必须发扬团结 协作的精神。这些经验对我们以后的学习、工作和生活都是一笔莫大的精 神财富,它将指引我们在梦想的道路上踏踏实实的努力,勇往直前,奋斗 一生。 团队感言 这次课程设计持续了两个周,还是颇有感触的。 这次的课程设计让我头大,连续失眠几天。其中有急躁,也有欢喜。 作为小队长,我有很多不足之处,三个人之间信息沟通不畅,致使人员和 时间的浪费。 首先是信息的查找,算术表达式的表达式在网上很多,但绝大多数不 能正确运行,找到几个能运行的,可是不能满足条件,要么不能运算括号, 要么不能运行负数。 查了好久好多资料,包括逛程序编程论坛,向搜搜问问和百度知道专 家提问,结果也不近人意。终于在逛论坛时

32、,看到一个程序员,向其请教, 他很热心的给出程序。拿来复制运行,程序基本满足条件,然后向舍友请 教终于时程序完美运行。当时的感觉真的是柳暗花明,欣喜若狂! 虽然程序看不太懂,但会向同学们请教。另外就是报告的内容,写起 来感到好复杂。在整个课程设计的过程中还体会到一点就是, “书到用时方 恨少”。平时对编程方面的书看得比较少,就导致了现在编程的时候很吃 力,原本在完成程序之后想向其他组一样做一个漂亮的界面,可是我们三 个组内成员都不会做界面,之后就不了了之,直到最终也没能做出一个比 较出色的界面。 这次做程序设计比较可以肯定是大家都付出了很多的努力,其他两位 组员每天拿着电脑去教室查找程序。付出

33、了努力,最后将程序完成,我们 还是非常有成就感的。只要用心去做一件事,然后再付出比别人多许多倍 的努力,就一定能够做得很出色。 一个小组合作完成任务不是像我想象的那么简单,并不是简简单单得 分好工就能做得很出色的。还需要小组各成员的努力,成员之间的交流, 以及每个人之间的通力合作。谢谢我们组员们的共同努力。 孙建 。 姓 名 。 姓 名 最后,感谢老师在这次课程设计的悉心指导,祝老师身体健康,工最后,感谢老师在这次课程设计的悉心指导,祝老师身体健康,工 作顺利。作顺利。 附附 录录 一、的关键代码如下: #include #include #include #define MAX_DATA_B

34、IT 100 #define YES 1 #define NO 0 #define POINT_UNEXIST -15 #define MAXSIZE 100 int EXP_INIT=YES; int BRACKET_COUNT=0; /标识运算符,不包括括号 int iscalchar(char c); /标识空白字符,不包括换行符 int is_space(char c); /标识表达式第一个合法字符 int isFIRSTallow(char c); /标识表达式的合法字符 int isallow(char c); /函数,将字符串转换成双精度数 double char_to_doub

35、le(char DigitString,int markpot,int markend); /得到表达式的首项,并检查字符是否合法 int getexp(double *data,char *oprt); typedef struct char oprt_stackMAXSIZE; double data_stackMAXSIZE; char oprt_in,oprt_out,*oprt_curp; double data_in,data_out,*data_curp; stack; /* 一组栈操作函数 */ /*操作成功返回 1,失败返回 0 */ int PopData(stack *p

36、); int PushData(stack *p); int PopOprt(stack *p); int PushOprt(stack *p); void clear(stack *p); /语法检查函数,返回 2 表示表达式结束 int checkgram(int fsitua,int lsitua); /功能函数,比较两个运算符的优先级 int priority(char cal1,char cal2); /错误处理函数,丢弃出错后所有字符,并打印出错信息 void error(int state); /计算函数,有发现简单逻辑错误的功能 int calculat(double data

37、1,char oprt,double data2,double *result); stack STK; int main() int FState,LState,GramState,CalcuState; double result,TempData; char TempOprt; STK.data_curp=STK.data_stack; STK.oprt_curp=STK.oprt_stack; while(1) clear( EXP_INIT=YES; BRACKET_COUNT=0; LState=100; GramState=1; CalcuState=1; printf(请输入一

38、个正确的表达式 ); do FState=LState; if(LState=getexp( break; if(GramState=checkgram(FState,LState)0 TempData=STK.data_out; PopData( PopOprt( CalcuState=calculat(STK.data_out,STK.oprt_out,TempData, if(CalcuState0) break; STK.data_in=result; PushData( if(*STK.oprt_curp=( if(!(LState=3|LState=4|LState=7|LStat

39、e=8) PushOprt( if(LState=2|(LState=6 PushOprt( if(CalcuState0 putchar(n); if(STK.oprt_in!=n) while(getchar()!=n); STK.oprt_in=0; int isoprt( char c) if (c=+|c=-|c=*|c=/|c=) return 1; else return 0; int is_space(char c) if (c= |c=t|c=v) return 1; else return 0; int isFIRSTallow(char c) if (c=.|c=-|c=

40、(|isdigit(c) return 1; else return 0; int isallowed(char c) if (c=.|isoprt(c)|c=(|isdigit(c)|c=) return 1; else return 0; double char_to_double(char data,int markpot,int markend) int i; double sumz=0,sumf=0; if (data0!=-) for (i=0;imarkpot;-i) sumf=sumf*0.1+(datai-0); return sumz+sumf*0.1; else for

41、(i=1;imarkpot;-i) sumf=sumf*0.1+(datai-0); return -(sumz+sumf*0.1); int getexp (double *data,char *oprt) int c,i=0,mrkpot=POINT_UNEXIST; char tempMAX_DATA_BIT; while (is_space(c=getchar(); if (c=n) *oprt=c;return 8; if (!isallowed(c) return -1; if (EXP_INIT=YES) if(!isFIRSTallow(c) return -4; if(c=()+BRA

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论