软件工程Ⅱ:小学四则运算
作业要求来源于 https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2186
我的GitHub远端库 https://github.com/WAN-Y/gggit
一、题目要求:
像《构建之法》的人物阿超那样,写一个能自动生成小学四则运算题目的命令行 “软件”。
具体要求:任何编程语言都可以,命令行程序接受一个数字输入,然后输出相应数目的四则运算题目和答案。例如输入数字是 30, 那就输出 30 道题目和答案。 运算式子必须至少有两个运算符,运算数字是在 100 之内的正整数,答案不能是负数。 如:
23 - 3 * 4 = 11
扩展要求:
1) 要求能出和真分数 (二分之一, 十二分之五,等)相关的练习题。
2) 并且要求能处理用户的输入,并判断对错,打分统计。 要求能处理用户输入的真分数, 如 1/2, 5/12 等。
初步拟定要实现的功能后,估计一下自己需要花多长时间。编程过程中记录自己实际用了多长时间。
然后和同学们比较一下各自程序的功能、实现方法的异同等等。
写博客纪录自己实现的过程和思路。
二、个人软件过程耗时估计与统计表
PSP2.1 | Personal Software Process Stages | Time Senior Student | Time |
Planning | 计划 | 0.5 | 0.5 |
· Estimate | 估计这个任务需要多少时间 | 6 | 7 |
Development | 开发 | 6 | |
· Analysis | 需求分析 (包括学习新技术) | 0.5 | 0.5 |
· Design Spec | 生成设计文档 | 0 | 0.2 |
· Design Review | 设计复审 | 0 | 0.1 |
· Coding Standard | 代码规范 | 0.2 | |
· Design | 具体设计 | 2 | 1 |
· Coding | 具体编码 | 2 | 3 |
· Code Review | 代码复审 | 0.5 | 1 |
· Test | 测试(自我测试,修改代码,提交修改) | 0.5 | 0.5 |
Reporting | 报告 | 0 | 3 |
· | 测试报告 | 0 | |
· | 计算工作量 | 0 | |
· | 并提出过程改进计划 | 0 |
三、代码提交
实现过程和思路
我选择了c语言来编写这次的程序。
1.先写出获取题目数量的语句,并用for()循环体输出题目序号。(此后每输出一个序号就随机一个等式。)
printf("请输入题目数量:"); scanf("%d",&num); for(i=1;i<=num;i++) { printf("%d.\n",i); }
2.随机等式的“部件”。为运算数和运算符建立新变量,并获取循环数。
(运算符是通过随机获得0~3的数字,再用switch()语句分别对应+-×÷得出的。)
srand((int)time(0)); a=rand()%100; b=rand()%100; c=rand()%100; m=rand()%4; n=rand()%4; switch(m) { case 0: x='+'; break; case 1: x='-'; break; case 2: x='*'; break; case 3: x='/'; if(b==0) b=rand()%100; //避免除数为零 break; }
3.计算等式结果
switch(x) //从左到右算起 { case '*': v=a*b; //v变量存储第一次运算结果 break; case '/': v=(float)a/b; break; case '+': if(y!='*'&&y!='/') //需要先算后面部分时跳过 {v=a+b;} break; case '-': if(y!='*'&&y!='/') //需要先算后面部分时跳过 {v=a-b;} break; } switch(y) //计算右半部分 { case '+': w=v+c; //w存储最终结果 break; case '-': w=v-c; break; case '*': if(x=='+') //1.从右往左算回去 {w=a+(b*c);} else if(x=='-') {w=a-(b*c);} else {w=v*c;}//2.顺序计算 break; case '/': if(x=='+')//1.从右往左算回去 {w=a+((float)b/c);} else if(x=='-') {w=a-((float)b/c);} else {w=v/c;}//2.顺序计算 }
4.若计算结果为负,重新执行循环体。
if(w<0) { goto loop; }
5.输出等式及结果。
for(i=1;i<=num;i++) { printf("%d.\n",i); printf("%d %c %d %c %d = ",formula[i][0],formula[i][1],formula[i][2],formula[i][3],formula[i][4]); printf("%.2f\n",result[i]); }
6.程序运行结果
感想和体会
1.这次写代码的过程依旧犯了些基础错误,像是输出变量的时候加上了&取地址符,switch()里没有写break语句等等。
2.我发现:程序的主要功能写起来所花的时间是比较少的。在此次编码的过程里,耗时最长的居然是避免结果为负数这一附加要求。
虽然上面的代码里只有简单的一个go to语句,但实际上我思考所消耗的时间和写其他所有代码的时间是差不多的。
这是因为我的逻辑思考收到了比较大的考验。
什么时候结果会为负数?只有减法。
想把第一次和第二次的运算结果分开检验,那么有减号的情况有多少种呢?
非顺序的运算要怎么照顾到呢?用什么语句比较好?……
在思考的过程里大脑甚至当机了好一会儿,辛苦写出来的代码还总是运行失败,最后还是改成go to。
事先想好框架并构思好大致逻辑比闷头写要顺畅得多——也是我在此次作业中的一个小感想。
寻找可能会出bug的地方并尝试检验实在是很耗心力……
不难想象功能更复杂的软件要遇到多少更头大的问题,我想这就是软件工程之难的一个小缩影吧。