一、题目描述:
1. 使用 -n 参数控制生成题目的个数,例如
Myapp.exe -n 10 -o Exercise.txt
将生成10个题目。
2. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如
Myapp.exe -r 10
将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。
3. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。
4. 每道题目中出现的运算符个数不超过3个。
5. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,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. 四则运算题目1
2. 四则运算题目2
……
其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。
6. 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:
1. 答案1
2. 答案2
特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。
7. 程序应能支持一万道题目的生成。
8. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,并会输出所有题目中重复的题目,输入参数如下:
Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt -o Grade.txt
统计结果输出到文件Grade.txt,格式如下:
Correct: 5 (1, 3, 5, 7, 9)
Wrong: 5 (2, 4, 6, 8, 10)
Repeat:2
RepeatDetail:
(1) 2,45+32 Repeat 3,32+45
(2) 5,3+(2+1) Repeat 7,1+2+3
解释:
Correct: 5 ----5道题目正确,正确的题号 1,3,5,7,9
Wrong:5 -----5道题目错误,错误的题号 2,4,6,8,10
Repeat:2 2---组题目重复
(1) 第一组 题号2,题目 45+32 与题号3的题目重复,题号3为 32+45
(2)第二组 题号5,题目 3+(2+1) 与题号7的题目重复,题号7为 1+2+3
其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。
二、需求分析
用户在控制台输入想要输入的题目,难度系数,选择完毕后,系统根据选择的难度系数随机出题,其中表达式的数包含自然数和分数,分数以真分数和带分数的形式出现。用户填写答案,提交后可以进行判断正误,返回数据报告。程序支持10000道题目的生成,生成题目后将题目和题目的运算结果保存至文件保存,用户答题和答题后返回的数据报告均以文件形式保存在当前的目录下。
三、功能设计
基本功能
1.生成随机数(包括分数)
2.生成随机运算符
3.生成表达式
4.生成二叉树(用于计算,查重)
5.分数的计算
6.计算题目结果并输出到文件
7.比较答案并给出正确错误题号
四、设计实现
1.create.java
生成随机数,随机运算符,表达式,题目集
2.Calculate.java
计算结果并输出文档
3.Result.java
比较答案并给出正确错误题号
4.FenShu.java
分数的运算
5.Binary.java
生成二叉树
功能1.生成随机数

功能2.生成随机运算符
功能3.生成表达式
功能4.生成二叉树
功能5.分数的计算
功能6.计算题目结果
功能7.比较答案
五、代码说明
去除表达式首部和尾部的多余括号 当出现了括号不匹配时出现异常抛出
public TreeNode createTree(String expression) { /* * 去除表达式首部和尾部的多余括号 当出现了括号不匹配时出现异常 抛出 */ if (expression.indexOf("(") == 0) { for (int i = 0; i < expression.length(); i++) { if (expression.startsWith("(") == true) { if (expression.endsWith(")") == true) { expression = expression.substring(1, expression.length() - 1); } else { /* * 抛出异常 括号不比配 */ } } } } char[] exp = expression.toCharArray(); TreeNode newNode = new TreeNode(); String leftString = new String(); String rightString = new String(); String stack = new String(); // 用于存储括号的栈 当表达式检测完毕后 若栈不为空 这说明括号使用不合法 if (checkOperator(expression) == true) { int index = 0; // 记录最先扫描到的不在括号中的加号或减号 必为表达式运算的最后一次操作 int multi_div = 0; // 记录最先扫描到的不在括号中的乘号或除号的位置 只有在扫描不到加号和减号的前提下才有用 for (int i = exp.length - 1; i >= 0; i--) { if (exp[i] == ‘)‘) { stack = stack + exp[i]; } else if (exp[i] == ‘(‘) { if (stack.length() > 0) { stack = stack.substring(0, stack.length() - 1); } } else if (exp[i] == ‘+‘ && stack.length() == 0 || exp[i] == ‘-‘ && stack.length() == 0) { index = i; break; } else if (exp[i] == ‘/‘ && stack.length() == 0 || exp[i] == ‘*‘ && stack.length() == 0) { multi_div = i; } else { if (exp[i] < 48 || exp[i] > 57) { /* * 抛出异常 出现不合法的字符 */ } } } if (stack.length() != 0) { /* * 抛出异常 括号不匹配 */ } int separator; if (index != 0) { // 说明表达式的最后运算的为加法或减法 separator = index; } else { separator = multi_div; } newNode.data = String.valueOf(exp[separator]); int pos = 0; for (; pos < separator; pos++) { leftString = leftString + exp[pos]; } pos++; for (; pos < exp.length; pos++) { rightString = rightString + exp[pos]; } if (node == null) { node = newNode; } newNode.left = createTree(leftString); newNode.right = createTree(rightString); } else { newNode.data = expression; } return newNode; }
六、测试运行
题目文件test.txt
答案文件calculate.txt
数据报告文件result.txt
七、小结
此程序未实现查重功能,此程序已用二叉树结构存储日后在在这基础上完善已完成查重功能。此程序对于各种类型的操作数运算,是把各类型的操作数转换为分数形式运算,最后通过约分得出结果。
八、代码地址:https://gitee.com/jingyinglan/codes/iczorhpd2juakbw8vg4lx19