孙争,3118005106;邓富荣,3118005090
Myapp.exe -n 10
将生成10个题目。
Myapp.exe -r 10
将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。
.......
其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。
特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。
Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt
统计结果输出到文件Grade.txt,格式如下:
Correct: 5 (1, 3, 5, 7, 9)
Wrong: 5 (2, 4, 6, 8, 10)
其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 60 | |
Estimate | 估计这个任务需要多少时间 | 20 | |
Development | 开发 | 800 | |
Analysis | 需求分析(包括学习新技术) | 100 | |
Design Spec | 生成设计文档 | 30 | |
Design Review | 设计复审 | ||
Coding Standard | 代码规范 | 60 | |
Design | 具体设计 | 60 | |
Coding | 具体编码 | 300 | |
Code Review | 代码复审 | 60 | |
Test | 测试(自我测试、修改代码、提交修改) | 60 | |
Reporting | 报告 | 30 | |
Test Report | 测试报告 | 20 | |
Size Measurement | 计算工作量 | 10 | |
Postmortem&Process Improvement Plan | 事后总结,并提出过程改进计划 | 20 | |
Total | 合计 | 1630 |
编程语言的选择:java
需要用到的知识:IO流、JTable、栈、HashSet
结构分析
对于计算中心思想:用后缀表达式运算。
用逆波兰法;
中缀表达式转后缀表达式遵循以下原则:
1.遇到操作数,直接输出;
2、栈为空的时候遇到符号,入栈
3、遇到左括号将其入栈。
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;
5.遇到其他运算符’+’‘一’’*’’/‘时,弹出所有优先级大于或等于该运算符的栈项元素,然后将该运算符入栈;
6.最终将栈中的元素依次出栈,输出。
遇到的困难
IO流写入会覆盖之前的内容导致写入内容与预期不符,变量类型的转换问题,带分数的计算转化问题
根据需求,对每个功能进行细分、简化,找出每个功能的详细需求,把每个功能都实现完成,生成函数,然后考虑封装调用,在主函数中实现调用各个功能函数,完成开发。
main方法
public class major { public static void main(String[] args){ Choose choose = new Choose(); }
主要调用函数
public class Choose extends JFrame{ public Choose() { super("选择题目数量范围"); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(400, 300); this.setLocation(700, 250); this.setLocationRelativeTo(null); this.setResizable(false); this.setLayout(null); JLabel titleNumber = new JLabel("生成题目的数量:"); JLabel titleRange = new JLabel("题目的范围:"); Font font = new Font("微软雅黑", Font.BOLD, 15); titleNumber.setFont(font); titleRange.setFont(font); JTextField number = new JTextField(); JTextField range = new JTextField(); JButton create = new JButton("生成"); titleNumber.setBounds(50, 50, 160, 50); number.setBounds(200, 50, 100, 40); titleRange.setBounds(50, 120, 150, 50); range.setBounds(200, 120, 100, 40); create.setBounds(150, 190, 100, 50); this.add(titleNumber); this.add(number); this.add(create); this.add(titleRange); this.add(range); this.setVisible(true); create.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub ReadTxt rt = new ReadTxt(); int Number = Integer.parseInt(number.getText()); int Range = Integer.parseInt(range.getText()); try { String[] title = title(Number,Range); double[] rs = rt.readTxt("Answers.txt"); JOptionPane.showMessageDialog(null, "成功生成题目!"); dispose(); Jtable jTable_01 = new Jtable(title,rs); jTable_01.setVisible(true); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); JOptionPane.showMessageDialog(null, "生成失败!"); } //答案文件 } }); } //生成题目、答案,并写入文件 public String[] title(int number,int range) throws IOException { CalculateImp c = new CalculateImp(); Create_title c2 = new Create_title(); WriteTxt wt = new WriteTxt(); Vector title1 = new Vector(); String title_path = "Exercises.txt"; String result_path = "Answers.txt"; HashSet set = new HashSet(); ServerImp serverImp = new ServerImp(); for(int i = 0 ; i < number ; i++) { String title = c2.create_title(range,3); double result = Double.parseDouble(c.calculate(title.toCharArray())); if(result < 0.0 && i != 0) { i--; System.out.println(result); System.out.println("出现负数"); continue; } if(!serverImp.removeRepeat(title,set)){ //去除重复的函数,并把结果存储在set中 System.out.println("重复了"); i--; } } Iterator iterator = set.iterator(); int j = 0; while (iterator.hasNext()){ String title3 = (String)iterator.next(); title1.add(title3); System.out.println("第" + String.valueOf(j+1) + "道题目:" + title3 + " ="); wt.WriteTxt("第" + String.valueOf(j+1) + "道题目:" + title3 + " =", title_path); wt.WriteTxt("第" + String.valueOf(j+1) + "道题的答案:" + c.calculate(title3.toCharArray()),result_path); j++; } String[] title3 = new String[title1.size()]; for(int i = 0;i<title1.size();i++){ title3[i] = (String)title1.get(i); } return title3; } }
生成题目函数Creat_title
public class Create_title { public String create_title(int range, int num2) {//num:提目数 range:范围 num2:题目组成数量 Random random = new Random(range); String[] char_arrays = null; int num3 = (int) (Math.random() * num2);//分数的个数 int num4 = num2 - num3;//正数个数 int charNum = num2 - 1;//符号个数 int bracketL = 0;//(位置 int[] int_arrays = new int[num4 + num3 * 2]; boolean flag = isBracket(); if (flag) { char_arrays = returnChar(num3, charNum + 2, flag); } else { char_arrays = returnChar(num3, charNum, false); } for (int w = 0; w < num2; w++) { int_arrays[w] = random.nextInt(range); } String title = ""; if (char_arrays[0].equals("(")) { for (int i = 0; i < num2; i++) { title += char_arrays[i] + ((int) (Math.random() * range) + ""); } if (char_arrays[num2].equals(")")) { title += ")"; } } else { for (int i = 0; i <= num2; i++) { title += ((int) (Math.random() * range) + "") + char_arrays[i]; } } if (title.charAt(title.length() - 1) == ‘+‘ || title.charAt(title.length() - 1) == ‘-‘ || title.charAt(title.length() - 1) == ‘/‘ || title.charAt(title.length() - 1) == ‘*‘) { title = title.substring(0, title.length() - 1); } return title; } boolean isBracket() { return true; } String[] returnChar(int mark, int charNum, boolean flag) { Random random = new Random(); String[] char_array = new String[charNum]; if (flag) { int bracketL = random.nextInt(charNum - 2);//(位置,最后一位和倒数第二位不能是( int j = charNum - bracketL - 2; int bracketR = bracketL + random.nextInt(j) + 2;//)位置这个随机数可以生成0 if (bracketL != 0) { char_array[bracketL] = "+("; } else { char_array[bracketL] = "("; } if (bracketR == charNum - 1) { char_array[bracketR] = ")"; } else { char_array[bracketR] = ")-"; } } int mark1 = 0; while (true) { if (mark1 == mark) { break; } int i = (int) (Math.random() * charNum); if (char_array[i] == null) { char_array[i] = "/"; mark1++; } } int num = 0; while (true) { if (num == charNum) break; if (char_array[num] == null) { int i = (int) (Math.random()*4); switch (i) { case 0: char_array[num] = "*"; break; case 1: char_array[num] = "+"; break; case 2: char_array[num] = "-"; break; case 3: char_array[num] = "÷"; break; } } num++; } return char_array; } }
计算结果函数CalculateImp
public class CalculateImp { public String calculate(char[] str) { int j = 0; //中缀表达式转后缀表达式 double[] num = new double[100]; char[] operator = new char[100]; int index = 0; char[] stack = new char[100]; double[] stackj = new double[100]; int top = -1; int temp = 0; //正在拼写数字 int flag = 0;//表示是否执行数字 int flag2 = 0;//判断什么时候读完了 while (true) { if (j == str.length) { flag2 = 1; } if (flag2 == 0 && str[j] >= ‘0‘ && str[j] <= ‘9‘) {//读到数字 flag = 1; temp *= 10; temp += str[j] - ‘0‘; } else {//读到了符号,或者结束 if (flag == 1) {//如果在拼写一个数字就将一个数字输出 num[index] = temp; operator[index] = ‘?‘; index++; flag = temp = 0; } if (flag2 == 1) {//如果字符串已经结束 while (top >= 0) { int q = top--; if (stack[q] != ‘(‘) { operator[index++] = stack[q]; } } break; } else {//读到一个符号 if (top == -1 || str[j] == ‘(‘) { stack[++top] = str[j]; } else if (str[j] == ‘)‘) {//如果是右括号则一直出栈道左括号 while (top >= 0 && stack[top] != ‘(‘) { operator[index++] = stack[top--]; } } else if (str[j] == ‘*‘ || str[j] == ‘/‘) {//如果是乘除,则乘除出栈,新符号入栈 while ((top > 0) && (stack[top] == ‘*‘ || stack[top] == ‘/‘)) { operator[index++] = stack[top--]; } stack[++top] = str[j]; } else {//如果是加减,则四则运算出栈,新符号入栈 while ((top >= 0) && (stack[top] !=‘(‘)) {//>=0是为了确保第0位可以出栈 operator[index++] = stack[top--]; } stack[++top] = str[j]; } } } j++; } top = -1; double temp1 = 0; double temp2 = 0; for (int i = 0; i < index; i++) { if (operator[i] == ‘?‘) { stackj[++top] = num[i]; } else { temp1 = stackj[top--]; temp2 = stackj[top--]; switch (operator[i]) { case ‘+‘: stackj[++top] = temp2 + temp1; break; case ‘-‘: stackj[++top] = temp2 - temp1; break; case ‘*‘: stackj[++top] = temp2 * temp1; break; case ‘÷‘: stackj[++top] = temp2 / temp1; break; case ‘/‘: stackj[++top] = temp2 / temp1; break; } } } double result = stackj[0]; return result + ""; } }
去重函数ServerImp
public class ServerImp { //去重 boolean flag = true; public boolean removeRepeat(String title, HashSet set) { if(title.length()>5){ set.add(title); } if (title.charAt(0) == ‘(‘) { if (title.length() == 5) {//只有出现两个数字相加的时候才允许运行 add(title, set, true); System.out.println("didid"); } } else if (title.length() == 3) { add(title, set, false); System.out.println("lal"); } return flag; } void add(String title, HashSet set, boolean flag) {//用于两个数相加的情况 String a = null; String b = null; String c = null; if (flag) { a = String.valueOf(title.charAt(1)); c = String.valueOf(title.charAt(2)); b = String.valueOf(title.charAt(3)); } else { a = String.valueOf(title.charAt(0)); c = String.valueOf(title.charAt(1)); b = String.valueOf(title.charAt(2)); } String temp = b + c + a; if (set.add(temp)) { set.remove(temp); set.add(a + c + b); this.flag = true; } else { this.flag = false; System.out.println("出现重复"); } } }
首先生成20道题目
提交答案后生成答题情况
写入的文件
生成10000道题目
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 60 | |
Estimate | 估计这个任务需要多少时间 | 20 | |
Development | 开发 | 1200 | |
Analysis | 需求分析(包括学习新技术) | 150 | |
Design Spec | 生成设计文档 | 30 | |
Design Review | 设计复审 | ||
Coding Standard | 代码规范 | 60 | |
Design | 具体设计 | 60 | |
Coding | 具体编码 | 300 | |
Code Review | 代码复审 | 60 | |
Test | 测试(自我测试、修改代码、提交修改) | 60 | |
Reporting | 报告 | 20 | |
Test Report | 测试报告 | 20 | |
Size Measurement | 计算工作量 | 10 | |
Postmortem&Process Improvement Plan | 事后总结,并提出过程改进计划 | 20 | |
Total | 合计 | 2070 |
这次项目是结对项目,不能自己干自己的了,不能想怎么干就怎么干,要考虑队友的想法、时间和能力,由于这次疫情的关系,我们不能面对面地交流,只能线上讨论,额外增加了讨论的时间,有时候找个Bug都要好久,但这些并不妨碍我们完成此次项目。
结对项目比上次的个人项目较难,所以分工很重要,开始时我们就讨论好各自负责的工作,交换各自的想法,在实际开发遇到的问题一起解决,这次项目使我们认识到,在团队项目开发中,分工合作、代码规范很重要,沟通交流更重要。这次项目也暴露了我们很多缺点,做事拖拉,编码不规范,细节不够重视,测试能力欠缺,debug速度不够,这些都是需要我们在日后的实际开发中一点一点地纠正的,我们也会不断学习,不断进步。
原文:https://www.cnblogs.com/frspring/p/12609824.html