这个作业属于哪个课程 | 软件工程课程 |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230 |
这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
成员一 | 32222004725乌克来·布拉什 |
成员二 | 3222004728钟慧雯 |
GitHub地址
https://github.com/wklay-77/Wklay-77
PSP表格:
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
· Estimate | · 估计这个任务需要多少时间 | 600 | 750 |
Development | 开发 | 210 | 320 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 60 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 (和同事审核设计文档) | 10 | 10 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 30 |
· Design | · 具体设计 | 60 | 50 |
· Coding | · 具体编码 | 300 | 360 |
· Code Review | · 代码复审 | 60 | 90 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 80 |
Reporting | 报告 | 30 | 30 |
· Test Report | · 测试报告 | 60 | 60 |
· Size Measurement | · 计算工作量 | 20 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 30 | 50 |
合计 | 1570 | 1980 |
一、项目需求分析
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为算术表达式。
3.需求:
-
使用 -n 参数控制生成题目的个数,例如 Myapp.exe -n 10 将生成10个题目。
-
使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如 Myapp.exe -r 10 将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然
数。该参数必须给定,否则程序报错并给出帮助信息。 -
生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1− e2的子表达式,那么e1≥ e2。
-
生成的题目中如果存在形如e1÷ e2的子表达式,那么其结果应是真分数。
-
每道题目中出现的运算符个数不超过3个。
-
程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8
× 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两
道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。 -
生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:
四则运算题目1
四则运算题目2
……
其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。 -
在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:
答案1
答案2
特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。 -
程序应能支持一万道题目的生成。
-
程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:
Myapp.exe -e .txt -a .txt -
统计结果输出到文件Grade.txt,格式如下:
Correct: 5 (1, 3, 5, 7, 9)
Wrong: 5 (2, 4, 6, 8, 10)
其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。
二、效能分析
1.改进的思路:
- 输入验证与错误处理:对用户输入进行有效的验证和错误处理,减少无效请求带来的性能消耗。
- 模块化设计:将功能拆分成独立的模块,每个模块负责一部分,有利于复用和维护。
2.性能分析的图:
3.Memory占用图:
三、设计实现过程
1.类与函数的设计分析:
类 Calculate: 主要用于处理数学表达式的计算。
-
方法 getResult(String s):
计算输入字符串 s 的结果。
先通过 PRNCal 方法计算后缀表达式的结果,然后对结果进行格式化,返回分数的标准形式。 -
方法 PRNCal(String s):
计算后缀表达式的结果。
使用栈结构处理运算符和操作数,支持四种基本运算(加、减、乘、除)。 -
方法 generate(String s):
将中缀表达式转换为后缀表达式(逆波兰表示法)。
使用栈结构处理运算符的优先级和括号。 -
辅助方法: 包括处理括号、字符串转换、操作符优先级比较、最大公约数和最小公倍数的计算等。
类 Check: 主要用于处理后缀表达式,构建二叉表达式树,并进行遍历。
-
方法 chaChong(String s):
接收一个字符串 s 作为输入,生成后缀表达式并调用构建二叉树的函数。
返回后缀表达式的字符串。 -
内部类 Node:
表示二叉树的节点,包含节点值和左右子节点。 -
方法 suffixExpressionTree(String suffixStr):
将后缀表达式转换为二叉表达式树。
使用栈结构来构建树,运算符节点的左右子节点根据优先级和比较规则进行选择。 -
方法 isOperator(String s):
判断给定字符串是否为运算符。 -
方法 PostOrderTravels(Node node):
进行后序遍历,并调用 visit 方法处理每个节点。 -
方法 visit(Node node):
访问节点并将节点值添加到结果字符串 str 中。 -
方法 compare(String a, String b):
比较两个分数的大小,使用 Calculate 类中的方法进行转换和比较。
类 CompareAnswer: 主要用于比较两个答案文件的内容,统计正确和错误的行数,并输出结果。
-
静态变量:
filePath2: 存储正确答案的文件路径(answer.txt)。
filePath3: 存储用户答案的文件路径(your-Answer.txt)。 -
方法 compare():
该方法负责读取两个文件的内容,逐行进行比较,统计正确和错误的答案,并将结果写入文件。
类 CreateFormula: 用于生成随机的数学算式。
-
静态变量:
operate: 存储可用的运算符,包括加法、减法、乘法和除法。 -
方法 Creating(int range):
接收一个整数 range 作为参数,用于限制生成的操作数的范围。
返回一个字符串,表示生成的数学表达式。 -
方法 getNum(int num):
随机生成操作数,可以是自然数、真分数或带分数。
根据随机生成的类型,生成相应格式的字符串表示。 -
方法 getOperate():
随机选择一个运算符并返回。
类 fenshu: 用于表示分数,包含分子和分母的属性。
- fenshu: 整数类型,用于表示分数的值。
- fenmu: 整数类型,表示分母。
- fenzi: 整数类型,表示分子。
Getter 和 Setter 方法: - getFenshu(): 返回 fenshu 的值。
- setFenshu(int fenshu): 设置 fenshu 的值。
- getFenmu(): 返回 fenmu 的值。
- setFenmu(int fenshu): 设置 fenmu 的值。
- getFenzi(): 返回 fenzi 的值。
- setFenzi(int fenzi): 设置 fenzi 的值。
类 FileWriting: 提供了一系列静态方法,用于文件的操作。
-
静态属性:
filePath, filePath2, filePath3, filePath4: 这些字符串常量分别表示不同文件的路径,包含 Exercises.txt、answer.txt、your-answer.txt 和 Grade.txt。 -
方法 createFile(File fileName):
创建一个新文件(如果该文件不存在)。 -
方法 readTxtFile(File file):
读取指定文件的内容,并将其作为字符串返回。 -
方法 writeTxtFile(String content, File fileName):
将指定内容写入文件,覆盖原有内容。 -
方法 fileChaseFW(String filePath, String content):
追加内容到指定文件的末尾。 -
方法 writter, writter1, writter2, writter3:
这些方法分别用于写入到不同的文件,调用 createFile 和 fileChaseFW。 -
方法 fileClear():
清空所有指定文件的内容。
类 HomePage: 该类包含一个 main 方法,负责程序的入口和主要逻辑。
-
方法 main(String[] args):
提示用户输入生成的题目数量和数值范围。
验证用户输入是否为整数。
调用 question 类的 Exam 方法生成题目。
提示用户是否需要批改答案。 -
方法 isInt(String string):
验证一个字符串是否为整数。 -
方法 input():
从控制台读取用户输入。
类 question: 包含一个方法 Exam,用于生成题目并处理重复题目。
-
方法 Exam(int count, int range):
根据给定的题目数量 count 和数值范围 range 生成题目。
检查生成的题目是否重复,并将题目和答案写入文件。 -
方法 deleteKuoHao(String str):
去掉字符串开头和结尾的括号(如果存在)。
2.关键函数:
-
方法 main(String[] args):
提示用户输入生成的题目数量和数值范围。
验证用户输入是否为整数。
调用 question 类的 Exam 方法生成题目。
提示用户是否需要批改答案。 -
方法 PRNCal(String s):
计算后缀表达式的结果。
使用栈结构处理运算符和操作数,支持四种基本运算(加、减、乘、除)。 -
方法 compare(String a, String b):
比较两个分数的大小,使用 Calculate 类中的方法进行转换和比较。 -
方法 Creating(int range):
接收一个整数 range 作为参数,用于限制生成的操作数的范围。
返回一个字符串,表示生成的数学表达式。
四、关键代码说明
main函数
代码:
public static void main(String[] args)
throws Exception
{
System.out.print("请输入生成的题目数量:");
String input1 = input();
while (!isInt(input1)) {
System.out.println("输入错误,请重新输入!");
input1 = input();
}
System.out.print("请输入题目的数值范围:");
String input2 = input();
while (!isInt(input2)) {
System.out.println("输入错误,请重新输入!");
input2 = input();
}
question exam = new question();
exam.Exam(Integer.parseInt(input1), Integer.parseInt(input2));
System.out.println("出题完毕,请到your-answer.txt作答!");
System.out.println("如需批改请按‘1’,任意键退出");
String input3 = input();
if (input3.equals("1")){
CompareAnswer.compare();
System.out.println("批改已完成,请到Grade.txt查看");
}
else
System.exit(0);
}
思路说明:
-
获取题目数量:
程序首先提示用户输入要生成的题目数量。
使用 input() 方法读取用户输入的字符串,并将其存储在 input1 中。
通过 isInt(input1) 方法检查输入是否为整数。如果不是整数,程序会提示用户输入错误,并要求重新输入,直到用户输入有效的整数。 -
获取数值范围:
程序接着提示用户输入题目的数值范围,使用相同的方式读取并验证输入。
将用户输入的数值范围存储在 input2 中,并再次使用 isInt(input2) 方法检查输入的有效性。 -
创建题目实例并生成题目:
创建 question 类的实例 exam。
调用 exam.Exam(Integer.parseInt(input1), Integer.parseInt(input2)) 方法,传入用户输入的题目数量和数值范围,生成数学题目。 -
输出完成信息:
程序在控制台输出“出题完毕,请到your-answer.txt作答!”的信息,提醒用户查看生成的题目文件。 -
选择是否批改答案:
程序询问用户是否需要批改答案,提示按“1”进行批改,任意键退出。
读取用户的输入 input3,如果用户输入“1”,则调用 CompareAnswer.compare() 方法进行批改,并在控制台输出批改完成的信息,提示用户查看 Grade.txt 文件。
如果用户输入其他内容,程序调用 System.exit(0) 退出。
五、测试运行
1.测试覆盖率:
2.运行结果:
六、项目总结
乌克来:这次同钟慧雯同学一起完成的结对项目任务,因为分工明确所以完成的非常顺利。也在这次结对项目中发现她对事反应能力很强,逻辑思维很清晰。
钟慧雯:这次和乌克来合作的结对项目完成得很顺利,我认为她的闪光点是能在发现问题时善于思考,很好地解决问题。很高兴能和她合作。
总结:在借助资料以及文献的帮助下,我们完成了这次项目,通过这次项目,我们对于java语言有了更加深入的了解,也意识到了结队合作的效率之高,相互之间取长补短,共同学习进步,对各自的编程能力与团队协作能力有了很大提升