小学四则运算
所属课程 | 广工软件工程社区 |
---|---|
作业来源 | 个人项目作业-论文查重 |
成员 | 杨镇兴3120004810 袁家俊3120004812 |
作业目标 | 1. 编程练习 2. 练习各种检测工具 3. 学习对项目进行单元测试 4.锻炼团队协作能力 |
github仓库 | 四则运算 |
1.题目
1题目:实现一个自动生成小学四则运算题目的命令行程序(也可以用图像界面,具有相似功能)。
2说明:
自然数:0, 1, 2, …。
真分数:1/2, 1/3, 2/3, 1/4, 1’1/2, …。
运算符:+, −, ×, ÷。
括号:(, )。
等号:=。
分隔符:空格(用于四则运算符和等号前后)。
算术表达式:
e = n | e1 + e2 | e1 − e2 | e1 × e2 | e1 ÷ e2 | (e),
其中e, e1和e2为表达式,n为自然数或真分数。
四则运算题目:e = ,其中e为算术表达式。
2.需求分析
- 通过命令行控制所需要生成的题目数量和生成的操作数的取值范围
- 随机生成不重复的题目并输出到文件
- 操作符和操作数的运算顺序完全相同则视为重复
- 计算题目并将答案输出到文件中
3.各模块设计
- ArgException 参数异常类
- CheckArg 检查参数
- CreateQuestion 创建题目
- CheckQuestion 检查题目是否重复
- DataNode 查重时所需要的数据结构
- CalculateOne 计算一道题目出现负数返回空
- CalcAll 计算所有题目
- Operator 计算类
- DataTofile 将数据输出到文件
关键算法为CheckQuestion
算法作用为检查题目是否重复
//当题库为空证明肯定不重复,直接返回true
//若不为空则遍历题库,根据题目要求可知,如果运算符的运算顺序相同且操作数也相同则重复,否则不重复
//先按实际运算符的执行顺序排序,排序结果放在List<dataNode>,dataNode中储存执行的运算符,和前后操作符的位置
//构建生成List<dataNode>的方法
public static void GetList(List<DataNode> list1, char[] symbol){
char[] symbol1=symbol.clone();
DataNode dataNode;
for(int i = 0;!Character.isSpaceChar(symbol1[i]); i++){//先找出括号,因为括号优先级最高,找出后为了后面方便也要把它删除
if(symbol1[i]=='('){
dataNode=new DataNode(symbol1[i+1],i,i+1);
symbol1[i+1]=' ';
symbol1[i+2]=' ';//把括号检测出来后删除
symbol1[i]=' ';//删除括号中的运算符,避免重复检测
int t=i;
for(;!Character.isSpaceChar(symbol1[t+3]);t++){
symbol1[t]=symbol1[t+3];
symbol1[t+3]=' ';
}
list1.add(dataNode);
}
}
for(int i=0;!Character.isSpaceChar(symbol1[i]);i++){//找乘除
if(symbol1[i]=='*'||symbol1[i]=='/'){
dataNode=new DataNode(symbol1[i],i,i+1);
list1.add(dataNode);
}
}
for(int i=0;!Character.isSpaceChar(symbol1[i]);i++){
if(symbol1[i]=='+'||symbol1[i]=='-'){
dataNode=new DataNode(symbol1[i],i,i+1);
list1.add(dataNode);
}
}
}
//其中dataNode
public class DataNode {
char symbol;//记录运算符
int first;//记录左操作数的位置
int second;//记录右操作数的位置
public DataNode(char symbol, int first, int second) {
this.symbol = symbol;
this.first = first;
this.second = second;
}
}
//然后拿待测数据和题库数据逐个比较,如果list<dataNode>的长度及list<dataNode>中symbol运算符都一样才有可能重复
//然后分情况比较
//比较运算符类
public static boolean CompareNumber(String[] a,List<DataNode> list1,String[] b,List<DataNode> list2){//如果重复返回true
//1.比较第一个节点的的左右两边
//2.true则判断第一个节点和第二个节点是否衔接,false则不重复
//3.衔接则比较衔接端的另一端的操作数相同则比较下一个操作数
//4.不衔接则比较两边操作数
int first1,first2;//左操作数所在的位置
int second1,second2;//右操作数的位置
for(int i=0;i<list1.size();i++){
first1=list1.get(i).first;//找出两组数据的第一个运算符的左右操作数
second1=list1.get(i).second;
first2=list2.get(i).first;
second2=list2.get(i).second;
//第一个比较两边
if(i==0){
if(a[first1].equals(b[first2])&&a[second1].equals(b[second2])||a[first1].equals(b[second2])&&a[second1].equals(b[first2])){//
continue;
}else {//其他情况直接break,后返回false
break;
}
}
if(i==1){//第二个运算符,先判断是不是衔接的
if(list1.get(i).first!=list1.get(i-1).second&&list1.get(i).second!=list1.get(i-1).first){//如果不衔接
if(list2.get(i).first!=list2.get(i-1).second&&list2.get(i).second!=list2.get(i-1).first){//检测数据也不衔接
if(a[first1].equals(b[first2])&&a[second1].equals(b[second2])||a[first1].equals(b[second2])&&a[second1].equals(b[first2])){//且重复,返回true,不用看最后一个
return true;
}else{
break;
}
}else{
break;
}
}else {//衔接,看下一个操作数(非衔接端)
if(list2.get(i).first==list2.get(i-1).second||list2.get(i).second==list2.get(i-1).first){//检测数据也要衔接
//找出要比较的操作数
int toCompare1,toCompare2;
if(list1.get(i).first==list1.get(i-1).second){
toCompare1=list1.get(i).second;
}else {//进来这里肯定是衔接的,else直接赋值另一个
toCompare1=list1.get(i).first;
}
if(list2.get(i).first==list2.get(i-1).second){
toCompare2=list2.get(i).second;
}else {
toCompare2=list2.get(i).first;
}
if(a[toCompare1].equals(b[toCompare2])){//比较重复则继续,如果只有两个字符则返回true
if(list1.size()==2){
return true;
}else{
continue;
}
}else{
break;
}
}else{
break;
}
}
}
if(i==2){//第三个字符,前面解决的第二个运算符且不衔接的情况,其实是三个运算符的情况,所以执行这段的情况只会是共有三个运算符且前面都衔接,只需要比较最后一个的second
if(a[second1].equals(b[second2])){//最后一个操作数是否重复
return true;
}else{
break;
}
}
if(list1.size()==1){//上面已经解决了2、3个运算符的算式重复的情况,现在补充只有一个字符且重复的情况,能执行到这怎么重复
return true;
}
}
return false;
}
4.模块性能分析
5.单元测试
参数异常测试
查重测试
操作数运算符生成测试
4. 最终结果测试
- 答题测试
- 测试覆盖率
6. 异常处理
//创建了ArgException异常类,当输出参数的数量或者形式出错时抛出异常
//当r或者n低于1时抛出异常
7.PSP
PSP2.1 | Personal Software Process Stages | 预计耗时 | 实际耗时 |
---|---|---|---|
Plane | 计划 | 80 | 110 |
Estimate | 估计要多少时间 | 20 | 20 |
Development | 开发 | 70 | 70 |
Analysis | 需求分析 | 70 | 70 |
Design Spec | 生成设计文档 | 30 | 40 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 | 20 | 20 |
Design | 具体设计 | 20 | 30 |
Coding | 具体编码 | 50 | 50 |
Code Review | 代码复审 | 20 | 20 |
Test | 测试 | 40 | 40 |
Reposting | 报告 | 70 | 70 |
Test Repor | 测试报告 | 50 | 60 |
Size Measurement | 计算工作量 | 20 | 30 |
Postmortem &Process Improvement Plan | 总结 | 20 | 20 |
合计 | 600 | 580 |
8. 项目小结
做完这次项目后发现先做需求分析文档和先确定所需要类再去开始写程序的重要性,否则在项目过程中会出现需要多次修改数据结构的问题
本文含有隐藏内容,请 开通VIP 后查看