一、题目要求
FileCal.java → 题库文件写入操作
GenerateCal → 根据用户参数生成四则远算,并组合成题库
com.cal.main包:
GetExercise → 生成四则运算程序入口,读取参数(-n,-r,-o)
VaildateExe → 检查四则运算结果程序入口,读取参数(-e)
com.cal.mold包:
FractionCal → 分数加减乘除计算结果
FractionStack → 分数分装
MainParameter → 程序入口参数分装
OutFileCal → 题库分装
RPNCalculator → 四则远算转后缀表达式,即进行逆波兰操作
trashcan包:
暂时没有用处或已经被替换的类
五、关键代码说明
package com.cal.mold; import java.util.HashMap; import java.util.List; import java.util.Stack; /** * 逆波兰表达式转换 * 计算四则运算结果 */ public class RPNCalculator { //运算符优先级 private static HashMap<String,Integer> opLs; private FractionCal fc = new FractionCal(); private String src; public RPNCalculator(String src) { this.src = src; if(opLs==null) { opLs = new HashMap<String,Integer>(6); opLs.put("+",0); opLs.put("-",0); opLs.put("*",1); opLs.put("/",1); opLs.put("%",1); opLs.put(")",2); } } //将中缀表达式转化为后缀表达式 public String toRpn() { String[] tmp = split(src); // 后缀栈 Stack<String> rpn = new Stack<String>(); // 临时栈 Stack<String> tmpSta = new Stack<String>(); for (String str : tmp) { if (isNum(str)) { //是操作数,直接压入结果栈 rpn.push(‘(‘+str+‘)‘); }else{ //是操作符号 if(tmpSta.isEmpty()) {//还没有符号 tmpSta.push(str); }else{ //判读当前符号和临时栈栈顶符号的优先级 if(isHigh(tmpSta.peek(),str)) { if(!str.equals(")")) { do{ //1在临时栈中找出小于当前优先级的操作符 //2压入当前读入操作符 rpn.push(tmpSta.peek()); tmpSta.pop(); }while(!tmpSta.isEmpty()&&(isHigh(tmpSta.peek(),str))); tmpSta.push(str); }else{ //是)依次弹出临时栈的数据,直到(为止 while(!tmpSta.isEmpty()&&!tmpSta.peek().equals("(")) { rpn.push(tmpSta.pop()); } if((!tmpSta.empty())&&(tmpSta.peek().equals("("))) {//弹出( tmpSta.pop(); } } }else if(!isHigh(tmpSta.peek(),str)){ tmpSta.push(str); } } } } while(!tmpSta.empty()) {//把栈中剩余的操作符依次弹出 rpn.push(tmpSta.pop()); } StringBuilder st = new StringBuilder(); for (String str : rpn) { st.append(str); } rpn.clear(); return st.toString(); } //分割(56+4)3*6+2=>(,56,+,4, private String[] split(String src) { StringBuilder sb = new StringBuilder(src.length()); for(char ch:src.toCharArray()) { if(ch==‘+‘||ch==‘-‘||ch==‘*‘||ch==‘*‘||ch==‘/‘||ch==‘(‘||ch==‘)‘||ch==‘%‘) { sb.append(","); sb.append(ch); sb.append(","); }else{ sb.append(ch); } } String string = sb.toString().replaceAll(",{2,}", ","); return string.split(","); } //比较操作符的优先级 private boolean isHigh(String pop, String str) { if(str.equals(")")) return true; if(opLs.get(pop)==null||opLs.get(str)==null) return false; return opLs.get(pop)>=opLs.get(str); } //是否是数字 public boolean isNum(String str) { for (char ch : str.toCharArray()) { if(ch==‘+‘||ch==‘-‘||ch==‘*‘||ch==‘*‘||ch==‘/‘||ch==‘(‘||ch==‘)‘||ch==‘%‘) return false; } return true; } //得到结果 public FractionStack calculate() { String rpn = toRpn(); Stack<FractionStack> res = new Stack<FractionStack>(); StringBuilder sb = new StringBuilder(); for(char ch:rpn.toCharArray()) { if(ch==‘(‘) { continue; }else if(ch>=‘0‘&&ch<=‘9‘||ch==‘.‘){ sb.append(ch); }else if(ch==‘)‘) { FractionStack fs = new FractionStack(); fs.setNumerator(Integer.parseInt(sb.toString())); fs.setDenominator(1); res.push(fs); sb = new StringBuilder(); }else{ if(!res.empty()) { FractionStack rear = res.pop(); FractionStack front = res.pop(); System.out.println("rear:"+rear.getRes()); System.out.println("front:"+front.getRes()); switch (ch) { case ‘+‘: res.push(fc.fracAdd(front, rear)); break; case ‘-‘: res.push(fc.fracSub(front, rear)); break; case ‘*‘: res.push(fc.fracMul(front, rear)); break; case ‘/‘: res.push(fc.fractDiv(front, rear)); break; } } } } FractionStack result = res.pop(); res.clear(); return result; } /* *计算生成题目的结果 */ public List<OutFileCal> GetExerciseRes(List<OutFileCal> caList){ for(int i=0;i<caList.size();i++){ String exe = caList.get(i).getCalExe(); RPNCalculator analyer = new RPNCalculator(exe); String res = analyer.calculate().getRealRes(); caList.get(i).setCalRes(res); } return caList; } }
上面为逆波兰表达式转换过程和计算四则运算结果
package com.cal.mold; public class FractionCal { //private FractionStack fs = new FractionStack(); //分数加法 public FractionStack fracAdd(FractionStack f1,FractionStack f2){ FractionStack fs = new FractionStack(); int first_numerator = f1.getNumerator();int first_denominator = f1.getDenominator(); int second_numrator = f2.getNumerator();int second_denominator = f2.getDenominator(); int denominator; int numerator; if(first_denominator==second_denominator) //分母相同时加分子 { denominator=first_denominator; numerator=first_numerator+second_numrator; } else //否则同分比较分子 { denominator=first_denominator*second_denominator; numerator=first_numerator*second_denominator+first_denominator*second_numrator; } int gcd = gcd(numerator,denominator); denominator = denominator / gcd; numerator = numerator / gcd; fs.setNumerator(numerator); fs.setDenominator(denominator); System.out.println("加法输出的结果是"+fs.getRes()); return fs; } //分数减法 public FractionStack fracSub(FractionStack f1,FractionStack f2){ FractionStack fs = new FractionStack(); int first_numerator = f1.getNumerator();int first_denominator = f1.getDenominator(); int second_numerator = f2.getNumerator();int second_denominator = f2.getDenominator(); int denominator; int numerator; if(first_denominator==second_denominator) //分母相同时加分子 { denominator=first_denominator; numerator=first_numerator-second_numerator; } else //否则同分比较分子 { denominator=first_denominator*second_denominator; numerator=first_numerator*second_denominator-first_denominator*second_numerator; } int gcd = gcd(numerator,denominator); denominator = denominator / gcd; numerator = numerator / gcd; fs.setNumerator(numerator); fs.setDenominator(denominator); System.out.println("减法输出的结果是"+fs.getRes()); return fs; } //分数乘法 public FractionStack fracMul(FractionStack f1,FractionStack f2){ FractionStack fs = new FractionStack(); int first_numerator = f1.getNumerator();int first_denominator = f1.getDenominator(); int second_numerator = f2.getNumerator();int second_denominator = f2.getDenominator(); int denominator; int numerator; denominator=first_denominator*second_denominator; numerator=first_numerator*second_numerator; int gcd = gcd(numerator,denominator); denominator = denominator / gcd; numerator = numerator / gcd; fs.setNumerator(numerator); fs.setDenominator(denominator); System.out.println("乘法输出的结果是"+fs.getRes()); return fs; } //分数除法 public FractionStack fractDiv(FractionStack f1,FractionStack f2){ FractionStack fs = new FractionStack(); int first_numerator = f1.getNumerator();int first_denominator = f1.getDenominator(); int second_numerator = f2.getNumerator();int second_denominator = f2.getDenominator(); int denominator; int numerator; numerator = first_numerator*second_denominator; denominator = first_denominator*second_numerator; int gcd = gcd(numerator,denominator); denominator = denominator / gcd; numerator = numerator / gcd; fs.setNumerator(numerator); fs.setDenominator(denominator); System.out.println("除法输出的结果是"+fs.getRes()); return fs; } //获取最大公约数 static int gcd(int x,int y){ int r; while( y!= 0) { r = x%y; x = y; y = r; } return x; } }
上面为分数计算器
六、运行测试
1.生成题库
2.题目结果验证
七、PSD统计
PSP2.1 | Personal Software Process Stages | Time Senior Student | Time | |
Planning | 计划 | 12 | 12 | |
· Estimate | 估计这个任务需要多少时间 | 12 | 12 | |
Development | 开发 | 6 | 6 | |
· Analysis | 需求分析 (包括学习新技术) | 6 | 10 | |
· Design Spec | 生成设计文档 | 5 | 6 | |
· Design Review | 设计复审 | 4 | 6 | |
· Coding Standard | 代码规范 | 3 | 3 | |
· Design | 具体设计 | 10 | 12 | |
· Coding | 具体编码 | 36 | 21 | |
· Code Review | 代码复审 | 7 | 9 | |
· Test | 测试(自我测试,修改代码,提交修改) | 13 | 21 | |
Reporting | 报告 | 9 | 6 | |
测试报告 | 3 | 2 | ||
计算工作量 | 2 | 1 | ||
并提出过程改进计划 | 3 | 3 |
八、作业小结
1.题目生成难度还有待开发
2.四则运算题目出题关键代码部分还可以改进,括号增减更加灵活
3.查重仍待开发
4.文件流读写代码冗余程度较大
GitHub:https://github.com/Umbrellazc/JavaCalculation