作业要求来自于https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2186
GitHub远程仓库的地址https://github.com/kunnkkk/16rg
一、题目要求:
像《构建之法》的人物阿超那样,写一个能自动生成小学四则运算题目的命令行 “软件”。
具体要求:任何编程语言都可以,命令行程序接受一个数字输入,然后输出相应数目的四则运算题目和答案。例如输入数字是 30, 那就输出 30 道题目和答案。 运算式子必须至少有两个运算符,运算数字是在 100 之内的正整数,答案不能是负数。 如:
23 - 3 * 4 = 11
扩展要求:
1) 要求能出和真分数 (二分之一, 十二分之五,等)相关的练习题。
2) 并且要求能处理用户的输入,并判断对错,打分统计。 要求能处理用户输入的真分数, 如 1/2, 5/12 等。
初步拟定要实现的功能后,估计一下自己需要花多长时间。编程过程中记录自己实际用了多长时间。
然后和同学们比较一下各自程序的功能、实现方法的异同等等。
写博客纪录自己实现的过程和思路。
二、个人软件过程耗时估计与统计表
PSP2.1 | Personal Software Process Stages | Time Senior Student | Time |
Planning | 计划 | 30min | 45min |
· Estimate | 估计这个任务需要多少时间 | 3h | 5h |
Development | 开发 | 1h | 1h |
· Analysis | 需求分析 (包括学习新技术) |
10min |
10min |
· Design Spec | 生成设计文档 | 0min | 0min |
· Design Review | 设计复审 | 5min | 3min |
· Coding Standard | 代码规范 | 3min | 3min |
· Design | 具体设计 | 20min | 30min |
· Coding | 具体编码 | 1h | 2h |
· Code Review | 代码复审 | 5min | 5min |
· Test | 测试(自我测试,修改代码,提交修改) | 30min | 50min |
Reporting | 报告 | 10min | 15min |
· | 测试报告 | 0min | 0min |
· | 计算工作量 | 2min | 2min |
· | 并提出过程改进计划 | 2min | 2min |
三、代码提交
提交源代码和可执行程序至github上,博客开头已给出github地址。
需要提交的应该有
- 项目的工程文件(可执行的应用程序)
- 项目的源代码(c文件)
- 一些必要的配置(无)
- 单独创建一个public子目录,存放编译后的可执行程序。(已创建子目录存放可执行的应用程序)
四、设计与结果
根据作业要求,分为了具体要求和扩展要求,所以在设计是,把这两个功能分开,令用户可以有针对性的练习。
而这两个功能都能实现询问测试题目数量、检测答案是否正确和计算答题准确率。
在设计这两个功能的时候也遇到比较困难的地方。
功能1:100以内四则运算 (四舍五入精确到小数点后两位)
- 对输入结果和正确答案进行四舍五入精确到小数点后两位的操作(已解决)
- 考虑两个运算符如何比较优先级(已解决)
功能2:20以内真分数的四则运算
- 设计分数加减乘除运算的逻辑关系(已解决)
- 如何让用户输入的字符与正确答案相比较(已解决,但方法一般还能优化)
- 如何约分(已解决)
- 如果得出的结果为整数,用户该如何输入(未解决,目前只能输入1/1代表整数)
五、部分详细代码
(1)功能1 | 获取随机运算符
//随机产生运算符 char createnumberop()
{ int op; op=rand() % 4+1; switch(op) { case 1:return'+'; case 2:return'-'; case 3:return'*'; case 4:return'/'; } return 0; }
(2)功能1 | 四则运算功能
if(result1 < 0 || result2 <0)//如果结果为非正数,则重新获取题目 { i--; continue; } else{ printf("%.f %c %.f %c %.f = ",a,op,b,op2,c); scanf("%f",&answer); if((op=='+' || op=='-') && (op2=='*' || op2=='/'))//若第二个运算符优先级更大 { if((int)(100.0*answer+0.5)/100.0==(int)(100.0*result2+0.5)/100.0 && result2 >=0)//四舍五入精确到小数点后两位 { printf("【回答正确!】 "); rightnumber++; } else{ printf("【回答错误!答案是:%.2f】 ",(int)(100.0*result2+0.5)/100.0); wrongnumber++; } } }
(3)功能2 | 获取公倍数与公约数
//获取公倍数 double gongbeishu(double b,double d) { double i,max; max=b>d?b:d;//比较分母大小 for(i=max;;i++) if((int)(i)%(int)(b)==0 && (int)(i)%(int)(d)==0)//计算最小公倍数 break; return i; } //获取公约数 double gongyueshu(double a,double c) { double i,min; min=a<c?a:c;//比较分子大小 for(i=2;i<=min;i++) if((int)(a)%(int)(i)==0 && (int)(c)%(int)(i)==0)//计算最小公约数 break; if(i>min) i=1; return i; }
(4)功能2 | 真分数逻辑运算
if(op=='+') { fenzihe0=beishu1*a + beishu2*c; fenmu=gongbeishu(b,d); fenzihe1=fenzihe0/gongyueshu(fenzihe0,fenmu); fenmu=fenmu/gongyueshu(fenzihe0,fenmu); if(fenzihe1<0 || fenmu<=0) { i--; continue; } else{ printf("(%.f/%.f) %c (%.f/%.f) = ",a,b,op,c,d); scanf("%d%c%d",&answer[0],&op2,&answer[1]); if(answer[0]/answer[1]==(int)fenzihe1/(int)fenmu && op2=='/') { printf("【回答正确!】 "); rightnumber++; } else{ printf("【回答错误!答案是:%.f/%.f】 ",fenzihe1,fenmu); wrongnumber++; } } }