1.远程仓库的码云项目地址:
2.PSP表格:
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 60*24*6天 | 60*24*6天 |
|
| 60*24*6天 | 60*24*6天 |
Development | 开发 | 60*24*6天 | 60*24*6天 |
|
| 60*24*2天 | 60*24*2天 |
|
| 0 | 0 |
|
| 0 | 0 |
|
| 5分钟 | 10分钟 |
|
| 10分钟 | 20分钟 |
|
| 60*24*4天 | 60*24*4天 |
|
| 60*6时 | 60*6时 |
|
| 60*6时 | 60*6时 |
Reporting | 报告 | 0 | 0 |
|
| 0 | 0 |
|
| 0 | 0 |
|
| 60分钟 | 60分钟 |
| 合计 | 60*24*6天 | 60*24*6天 |
3.解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程。
答:解题思路描述:刚开始拿到题目后,首先想到的问题是Python如何获得控制台输入的运算表达式。然后是如何判断输入是否包含非法字符,比如:英文,空格,!,@,#,¥,%,&,?等这些非运算字符。接下来想如何实现eval()函数功能。经过查找资料,发现实现这个函数功能有两种方法:一是正则表达式匹配,二是使用逆波兰算法。第一种方法判断优先级不是很好判断,所以选择了第二种方法来完成这次作业。最后就是查找逆波兰表达式的如何实现的原理。
4.设计实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?单元测试是怎么设计的?
答:把设计实现过程分为三个模块。第一模块是获取用户控制台输入,第二个模块是对输入表达式的异常处理,第三个模块是使用逆波兰表达式求解四则运算式。
有main.py和lib.py两个文件,共5个函数,分别为list_to_str:取消空格输入。
illegal_char:正则匹配是否包含非法字符。
get_nibolan:获得逆波兰表达式。
Operation:进行运算。
calculate:传入转换后的逆波兰判断优先级,进行运算。
单元测试有两个,第一个是捕获异常,第二个是生成逆波兰表达式。捕获异常类型有:英文,!,@,#,¥,%,&,?等这些非运算字符。当用户输入这些字符时,
- 用户输入异常捕获测试过程如下图:
输入:!、a-z、@、#
理论输出:输入包含非法字符,请重新输入
实际输出:输入包含非法字符,请重新输入
- 逆波兰测试如下图:
输入:3+4*(8-6)
理论输出:[3,4,8,6,'-','*','+']
实际输出:[3,4,8,6,'-','*','+']
流程图展示:
5.记录在改进程序性能上所花费的时间,描述你改进的思路,并展示一张性能分析图(由VS 2017的性能分析工具自动生成),并展示你程序中消耗最大的函数
答:所花费的时间如图所示:
6.代码说明。展示出项目关键代码,并解释思路与注释说明
答:先展示一下部分代码:
def get_nibolan(source): ''' source = "5*3+4+(2+5*4+(3*2))" # [5,3,*,4,+,2,5,4,*,+,2,3,*,+,+] ''' nibolan = [] st = [] # 一个栈 for ch in source: # 遍历整个表达式的每个字符 if ch == '(': st.append(ch) elif ch in digits: nibolan.append(int(ch)) elif not st and ch in priority.keys(): st.append(ch) elif st and ch in priority.keys(): for x in range(st.__len__()): z = st[-1] p = priority[z] if p >= priority[ch]: nibolan.append(st.pop()) else: break st.append(ch) elif ch == ')': for x in range(st.__len__()): if st[-1] == '(': st.pop() break else: nibolan.append(st.pop()) for x in range(st.__len__()): nibolan.append(st.pop()) return nibolan
这是百度百科逆波兰表达式的解释,它的语法规定,表达式必须以逆波兰表达式的方式给出。逆波兰表达式又叫做后缀表达式。这个知识点在数据结构和编译原理这两门课程中都有介绍,下面是一些例子:
正常的表达式 逆波兰表达式
a+b ---> a,b,+
a+(b-c) ---> a,b,c,-,+
a+(b-c)*d ---> a,b,c,-,d,*,+
a+d*(b-c)--->a,d,b,c,-,*,+
a=1+3 ---> a,1,3,+,=
http=(smtp+http+telnet)/1024 写成什么呢?
http,smtp,http,+,telnet,+,1024,/,=
下图是我举的一个例子:
3+4*(8-6)
这个式子的逆波兰表达式是 --->3,4,8,6,-,*,+
有两个列表,一个是nibolan列表,存放nibolan表达式,第二个列表是st列表,它用来存放运算符号,用来判断优先级,用户输入表达式,遍历其表达式,当遍历的是数字时,添加到nibolan列表里,当是运算符时,放到st列表进行运算,当遍历到第二个运算符时,判断这个运算符和刚才运算运算符的优先级的高低,如果大于第一个运算符的优先级,那么把这个运算符放到nibolan列表里,如果遍历的是”(“放到st列表进行堆栈,他的优先级最高,接着往下遍历,当遍历到下一个运算符时,将放到st列表堆栈,继续遍历运算符,当遍历的运算符优先级大于上一个运算符优先级时,把该运算符放入nibolan列表,如果小于继续堆栈,直至遍历到”)”;把st列表倒叙放入libolan列表,当在st列表中取到”(”时,不把该符号放入nibolan列表。
7.结合在构建之法中学习到的相关内容与个人项目的实践经历,撰写解决项目的心路历程与收获。
答:就我们这次实验的编程而言,我觉得我学到了很多东西,也提高了我们编程的效率,可以说是事半功倍的。我认为,设计编程的优势主要就在于设计思路。总的来说,自己在编程时犯下的错误,有些尽管很简单,但却难以发现,但是耐下性子总会找到原因的。