【vc++精品源码栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了vc++精品源码-【精品】模拟计算器程序-数据结构与算法课程设计报告 - 其它资料的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
合肥学院计算机科学与技术系 课程设计报告 2009~2010 学年第二学期 课程 数据结构与算法 课程设计名称 模拟计算器程序 学生姓名 桂俊飞 学号 0804012021 专业班级 08 计本(2)班 指导教师 王昆仑 张贯虹 2010 年 6 月一:问题分析和任务定义 本程序写的是模拟计算器。
要求设计一个模拟计算器的程序,要求对包含加、减、乘、除、括号运算符及 SQR 和ABS 函数的任意整型表达式进行求解。
这里可以做一个扩展,比如实现求某数的N次方,求模,一些常用的三角函数等。
这个程序实际上就是对一个表达式进行计算。
而一个算术表达式中包含各种运算符,每个运算符的等级可能会不同,这就成了本程序需要解决的一个主要的问题之一了。
另外计算器中需要有各种数学函数,比如:abs sqrt sin cos tan 等,如何对这些函数进行处理,也是本程序能成功的一个关键。
还有一个问题就是如何处理操作符和操作数之间的关系也是一个要点。
例如:123-2/1,经过怎么样的变换和处理能得出结果5。
数据的输入这里应该要用字符,然后通过字符和整形之间的关系进行转换即可,这样处理的话,就方便很多了。
二:概要设计和数据结构选择 输入的时候将一个算术表达式用一个字符数组来接收,故需要对这个数组进行处理,让操作数和操作符分开,这里我想把开始的算术表达式转换成一个后缀表达式,这样在进行计算的时候就简单多了。
而在转换的过程中,对运算符的处理极为重要,这里运用堆栈,用堆栈的先进后出的特点,来处理运算符优先级的问题,让其成功转换成后缀表达式。
而在对后缀表达式进行处理的时候,又需要一个堆栈,这个堆栈存放操作数的。
并将运算结果存入该栈中。
两个堆栈的数据结构如下: struct char dataMaxlen int top optr //定义运算符栈struct double dataMaxlen int topopnd //定义操作数栈这里定义了类型,并且一起定义了两者类型的对象 optropnd。
在将算术表达式转换成后缀表达式,定义 change 函数;在对后缀表达式进行处理时,定义 jisuan 函数,另外本程序有个欢迎界面,由 meun 函数实现。
因此主函数于各函数之间的关系为: meunmain change jisuan本程序实现的流程:这里的两个主要的函数具体算法在详细设计中有说明。
三:详细设计和编码 首先定义两个数组,p400用来存放算术表达式,q400用来存放后缀表达式。
由前面的数据结构定义两个对象optr,opnd。
当输入一个表达式后,定义 i 作为 q的下标,定义 dh1 表示是负号,初始化运算符栈 optr.top-1让后对p进行扫描,当p指向的为数字字符,则将此字符如q,后在往q中输入#,具体为: while pgt0 ampamp plt9 qipi p if p. qi. i p while pgt0 ampamp plt9 qipi p qi i dh0p 后移,继续扫描,当遇到+或-时,执行 if dh1 if p- optr.topoptr.dataoptr.top p break while optr.top-1 ampamp optr.dataoptr.top qioptr.dataoptr.top optr.top-- i optr.topoptr.dataoptr.topp p dh0 break当遇到或/时,先查看操作符栈中是否有优秀级比它大的或者一样大的运算符,有的话就将其他的出栈,最后自己入栈。
执行: while optr.dataoptr.top optr.dataoptr.top/ optr.dataoptr.tops qioptr.dataoptr.top optr.top-- i optr.topoptr.dataoptr.topp p dh0 break当遇到(时,此时不需要别的其他的操作,只需将其入操作符栈,并将 dh0当遇到)时,此时需要将(之前的操作符全部出栈,具体操作如下: while optr.dataoptr.top qioptr.dataoptr.top optr.top-- i optr.top-- p dh0 break当遇到时,根据运算符的优先级,执行: while optr.dataoptr.top qioptr.dataoptr.top optr.top--i optr.topoptr.dataoptr.topppdh0break遇到%时的操作和差不多,这里就不做介绍了。
当遇到数学函数的相关符号时, 这里以 sin 为例,当扫描s时,还需要扫描后面的两个字符,当它们是 in 时,说明就是 sin 函数的符号,此时将此函数的标志入操作符栈,当其为 qrt 时,说明是 sqrt 函数,此时将 sqrt 函数的标志入栈,这里的标志是自己定的。
如果都不是上面两种情况,说明输入有误,跳回。
具体的程序如下: ifp1i p1Iampampp2n p2N optr.topoptr.dataoptr.tops p3 dh0 break else ifp1q p1Qampampp2r p2Rampampp3t p3T optr.topoptr.dataoptr.topq p4dh0break else coutltltendlltltquot有错误符号quotltltendl return error 其他的数学函数的操作都是类似的,这里就不一一说明了。
这里值得注意的是,当将p扫描完时,操作符栈并未一定为空,故需要将操作符栈里的数据全部出栈:while optr.top-1 qioptr.dataoptr.top i optr.top-- 以上是将算术表达式转换成后缀表达式。
还要对后缀表达式进行计算,才能得到结果。
首先还是对表达式进行扫描,遇到数字符时,先将其转换成整形后,再判断是否有小数点存在,继续扫描直到遇到运算符,让后通过运算,将次数转换成小数,最后入栈。
具体程序实现:d0 while qgt0 ampamp qlt9 d10dq-0 q x0.1 if q. q while qgt0 ampamp qlt9 ddxq-0 x0.1 q 当遇到操作符时,为双目运算符时,只需要将操作数栈的栈顶和次栈顶数拿出来进行相应的计算,并将其压入次栈顶。
为单目运算符时,只需将操作数栈顶元素进行运算即可,并将运算符压入栈即可。
这里以 / 和sin为例。
其余的均和此类似。
if opnd.dataopnd.top0 opnd.dataopnd.top-1opnd.dataopnd.top-1/opnd.dataopnd.top else coutltltendlltltquot除数不能为零quotltltendl return error 和opnd.top--breakopnd.dataopnd.topsinopnd.dataopnd.top当 q 都扫描完时, 返回操作数栈顶元素就是计算的结果。
四:上机调试在语法上的错误,出现过很多,比如少了一个括号,少了个分号,这些问题都是日常写程序中经常出现的问题,想要避免有点难,不过这些错误根据编译器的提示和警告,就能很快的该出来。
就图 1 中出现的问题,这个问题是在define error 1234567 时出现的,这个问题我一直想不同,我定义 123456789 时可以通过编译,而变成 1234567 就不行了,通过向老师请教,发现这里的 error 和编译器里的定义重合了,故不能通过。
解决办法是将这里的 error改成 derror,这样在函数中 error 相应的也要该。
在逻辑上的错误,主要就是算法中出现的问题,本程序中的算法有点复杂,在表达式转换成后缀表达式的过程中就出现了很多的错误。
这里举出一个简单的错误,由于本程序在写的时候, 定义了 derror1234567 在程序中就不能出现这个计算结果,虽然它超过了本程序的能处理的范围,可是其结果还是 1234567,故返回主函数时,在 if changepq1 kjisuanq ifkderror coutltltquotquot else coutltltquot计算结果为:quotltltkltltendl 这里就会出错。
导致图中的错误。
解决办法,这里我对这中情况没有做特殊的处理。
应为在实际的运算过程中,很少有 1234567 这个结果出现,几乎是不出现的。
如何去定义这个数,一直是个问题。
本程序的,在定义的时用了两个数组,故其空间复杂度是 n,在算法上,这里我用了一个死循环,当输入不为 0 时, 会一直运行。
所以只讨论运行一次的时间复
上一篇:
【精品】野火stm32
下一篇:
不规则零件优化排样的神经网络混合优化算法