结对编程作业(JAVA实现)

github地址:https://github.com/IMFatDragon/sizeyunsuan.git

完成者:

周惠龙  3117004638 

陈浩峰 3117004603

 

一、项目相关要求
  1. 使用 -n 参数控制生成题目的个数,例如 SiZeYunSuan.exe -n 10 将生成10个题目。(完成)
  2. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如SiZeYunSuan.exe -r 10 将生成10以内(不包括10)的四则运算题目。(完成)
  3. 生成的题目中计算过程不能产生负数,即算术表达式中如果存在形如e1 − e2的子表达式,必须e1 ≥ e2(完成)
  4. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。(完成)
  5. 每道题目中出现的运算符个数不超过3个。(完成)
  6. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。(完成)
  7. 生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:(完成)
      1. 四则运算题目1
      2. 四则运算题目2
      ……
      其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2'3/8。
  1. 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:(完成)
      1. 答案1
      2. 答案2
      特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。
  1. 程序应能支持一万道题目的生成(完成)
  2. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:(未完成)
      Myapp.exe -e .txt -a .txt  统计结果输出到文件Grade.txt,
      格式如下: Correct: 5 (1, 3, 5, 7, 9)Wrong: 5 (2, 4, 6, 8, 10)
 
二、需求分析
  
从整体需求来看,大致可以分成三个模块:表达式生成模块、表达式运算模块、运算结果检验模块。
  • 表达式生成模块:表达式包括运算符部分(加减乘除)、数字部分(自然数,真分数,带分数)、括号部分。数值部分利用random对象的nextInt方法随机从1开始生成,其中分子随机数的数值范围是比分母小1,保证生成的数字不出现假分数的情况;运算符的个数是利用函数随机生成1-3之间的自然数,加减乘除的符号也是利用随机数1-4来生成;符号部分利用next Boolean方法根据true或者false来决定括号的生成,该过程中利用一个变量来标记括号范围。
  • 表达式运算模块:上述模块生成的表达式只是初步的表达式,运算功能是利用后缀表达式来实现的,生成后缀表达式后再将表达式的所有数值转化为分数形式,统一方便计算。为保证该过程中不出现负数运算,凡是进行减法运算的操作,都会对运算结果进行检验,一旦出现负数则丢弃当前表达式,直到再次生成的表达式符合要求,同时在此过程进行表达式的重复判断,将每一个当前非负表达式与已生成表达式进行查重检验,满足条件则加入Arraylist中,同时保存运算结果。
    •   查重检验:将后缀表达式转换为查重表达式,查重表达式的结果为运算符在先,后面跟着该运算符的操作数,例如(1+2)*3-4,后缀表达式为:12+3*4-,按照查重表达式的结构为:+12*3-4,查重过程中只需要判断查重表达式是否一致,或者在查重表达式中第一个字符'+'或'*'的情况下后续的两个操作数交换位置后是否一致即可。也就是说+12*3-4与+21*3-4的表达式是一致的。举个表达式不重复的例子:1+2+3和3+2+1,查重表达式分别为+12+3和+32+1,查重表达式不相同,即使交换'+'后面的两个操作数也无法一致,故这两个表达式不重复。
  • 运算结果检验模块:将最终符合要求的表达式存入当前目录下的Question.txt文件,正确答案保存在Answer.txt文件中,并对运算结果进行检。
三、设计思路
 
1.整体结构:
2.生成表达式:
四、模块代码说明
1、随机生成表达式:
  1 package Calculation;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Random;
  5 import java.util.Scanner;
  6 
  7 
  8 public class Ran_Expression {  //随机生成初步的表达式
  9 
 10 
 11 
 12         public static char[] ysf={'+','-','*','÷'};
 13         public static String exp_str;//四则运算表达式
 14         
 15         //获取输入
 16         public static String getScanner(){
 17             Scanner scan=new Scanner(System.in);
 18             String input=scan.nextLine();
 19             scan.close();
 20             return input;
 21         }
 22         
 23         
 24         //随机获取运算符+ - * ÷
 25         public static char getysf(){
 26             Random ran=new Random();
 27             int ysfNum=ran.nextInt(4);
 28             return ysf[ysfNum];
 29         }
 30         
 31         /**
 32          * 获取操作数
 33          * @param range 数值范围
 34          * @return
 35          */
 36         public static String getNumber(int range){
 37             Random ran=new Random();
 38             int index=ran.nextInt(3);
 39             String num="";
 40             
 41             /**
 42              * 随机获取数字,0获取自然数,1获取真分数,2获取带分数
 43              */
 44             if(index==0){//自然数
 45                 Random ran0=new Random();
 46                 num=ran0.nextInt(range-1)+1+"";
 47             }
 48             if(index==1){//真分数
 49                 Random ran1=new Random();
 50                 int fenmu=ran1.nextInt(range-2)+2;//分母[2,range)
 51                 int fenzi=ran1.nextInt(fenmu-1)+1;//分子
 52                 num=fenzi+"/"+fenmu+"";
 53             }
 54             if(index==2){//带分数
 55                 Random ran2=new Random();
 56                 int leftNum=ran2.nextInt(range-1)+1;//左整数部分
 57                 int rightFM=ran2.nextInt(range-2)+2;//右真分数部分-分母[2,range)
 58                 int rightFZ=ran2.nextInt(rightFM-1)+1;//右真分数部分-分子
 59                 num=leftNum+"'"+rightFZ+"/"+rightFM+"";
 60             }
 61             return num;
 62         }
 63         
 64         /**
 65          * 去表达式最前和最后的括号
 66          * @param str表达式
 67          * @return
 68          */
 69         public static String deleteKuoHao(String str){
 70             if((str.substring(0, 1).equals("(")) && (str.substring(str.length()-1).equals(")"))){
 71                 str=str.substring(1, str.length()-1);
 72             }
 73             return str;
 74         }
 75         
 76         
 77          //生成四则运算表达式
 78          //range题目中操作数的范围
 79         public static ArrayList<String> creatAc(int range){
 80             Random ran4=new Random();
 81             ArrayList<String> list=new ArrayList<String>();//存放每个表达式中的运算符和操作数
 82             boolean zuoKuoHao=false;//左括号
 83             boolean youKuoHao=false;//右括号
 84             boolean tem=false;
 85             int ysfNum=ran4.nextInt(3)+1;//每个表达式运算符个数1-3个
 86             exp_str="";
 87             
 88             //------------开始生成--------------
 89             for(int j=0;j<ysfNum;j++){
 90                 
 91                 //决定是否加入左括号
 92                 if(!zuoKuoHao && ran4.nextBoolean()){
 93                     exp_str+="(";
 94                     list.add("(");
 95                     zuoKuoHao=true;
 96                 }
 97                 String sz1=getNumber(range);
 98                 exp_str+=sz1;
 99                 list.add(sz1);
100                 //决定是否加入右括号
101                 if(zuoKuoHao && !youKuoHao && tem){
102                     if(ran4.nextBoolean()){
103                         exp_str+=")";
104                         list.add(")");
105                         youKuoHao=true;
106                     }
107                 }
108                 char char1=getysf();
109                 exp_str+=char1;
110                 list.add(char1+"");
111                 if(zuoKuoHao){
112                     tem=true;
113                 }
114             }
115             String sz2=getNumber(range);
116             exp_str+=sz2;
117             list.add(sz2);
118             if(zuoKuoHao && !youKuoHao){
119                 exp_str+=")";
120                 list.add(")");
121             }
122             exp_str=deleteKuoHao(exp_str);//去掉开头和结尾均为括号
123             //------------结束生成--------------
124             
125             System.out.println("生成中,请稍等:"+exp_str);
126             return list;
127             
128         }
129         
130         
131 
132 }

 

 
2、生成后缀表达式
  1 package Calculation;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Stack;
  5 
  6 
  7 public class After_Expression {  //生成后缀表达式
  8         /**
  9          *  将中序表达式转换成后序表达式
 10          * @param str 生成的中序表达式
 11          */
 12         public static Stack<String> toAfter_Expression(ArrayList<String> list){
 13             Stack<String> stack=new Stack<String>();//
 14             Stack<String> right=new Stack<String>();//右序表达式
 15             String ysf;//运算符
 16                 
 17             for(int i=0;i<list.size();i++){
 18                 String ch=list.get(i);
 19                 if(isysf(ch)){//当前字符为运算符
 20                     if(stack.empty()==true || ch=="("){//栈为空或者为(直接入栈
 21                         stack.push(ch);
 22                     }else{//非栈空、非左括号
 23                         if(ch==")"){//如果为)
 24                             while(true){//将(后的运算符出栈并加到后续表达式中
 25                                 if((!stack.empty()) && (!stack.peek().equals("("))){
 26                                     ysf=stack.pop();
 27                                     right.push(ysf);
 28                                 }else{
 29                                     if(!stack.empty())//如果栈顶元素为(
 30                                         stack.pop();
 31                                     break;
 32                                 }
 33                             }
 34                         }else{//非栈空、非左括号、非右括号
 35                             while(true){//栈不为空,优先级低
 36                                 if(!stack.empty() && priority(ch,stack.peek())){
 37                                     ysf=stack.pop()+"";
 38                                     if(!ysf.equals("(")){
 39                                         right.push(ysf);
 40                                     }
 41                                 }else{
 42                                     break;
 43                                 }
 44                             }
 45                             stack.push(ch+"");
 46                         }
 47                     }
 48                     
 49                 }else{
 50                     right.push(ch+"");//操作数
 51                 }
 52             }
 53             while(!stack.empty()){
 54                 ysf=stack.pop()+"";
 55                 if(!ysf.equals("("))
 56                     right.push(ysf);
 57             }
 58             return right;
 59         }
 60         
 61     
 62         // 判断是否为运算符
 63         public static boolean isysf(String ch){
 64             if((ch.equals("+"))||(ch.equals("-"))||(ch.equals("*"))||(ch.equals("÷"))||(ch.equals("("))||(ch.equals(")")))
 65                 return true;
 66             else 
 67                 return false;
 68         }
 69 
 70         /**
 71          * 设置运算符的优先级别
 72          * @param ysfout当前中序表达式字符
 73          * @param ysfin栈中字符
 74          * @return
 75          */
 76         public static boolean priority(String ysfout, String ysfin) {
 77             int m = -1, n = -1;
 78             String a_ysf[][] = { { "+", "-", "*", "÷", "(", ")" },
 79                     { "+", "-", "*", "÷", "(", ")" } };
 80             int first[][] = { { 1, 1, 2, 2, 2, 0 }, { 1, 1, 2, 2, 2, 0 },
 81                     { 1, 1, 1, 1, 2, 0 }, { 1, 1, 1, 1, 2, 0 },
 82                     { 2, 2, 2, 2, 2, 0 }, { 2, 2, 2, 2, 2, 2 } };
 83             for (int i = 0; i < 6; i++) {
 84                 if (ysfin.equalsIgnoreCase(a_ysf[0][i]))
 85                     m = i;
 86             }
 87             for (int i = 0; i < 6; i++) {
 88                 if (ysfout.equalsIgnoreCase(a_ysf[1][i]))
 89                     n = i;
 90             }
 91             if (m == -1 && n == -1)
 92                 return false;
 93             else if (m == -1 && n != -1)
 94                 return false;
 95             else if (m != -1 && n == -1)
 96                 return true;
 97             else if (first[m][n] == 1) {
 98                 return true;
 99             } else
100                 return false;
101         }
102 
103 }

 

3、将表达式中所有数值转为分数形式
 1 package Calculation;
 2 
 3 import java.util.Stack;
 4 
 5 public class CaoZuoShu_handle {
 6 
 7 
 8      //该类将后续表达式stack转化为有分子分母的后续表达式
 9      //存于Calcul_Expression对象的calculatorStack中
10 
11     Stack<Calcul_Expression> posfixStack;
12         
13         public CaoZuoShu_handle(Stack<String> stack) {
14             Stack<Calcul_Expression> stack1 = new Stack<>();//中间栈
15             Stack<Calcul_Expression> stack2 = new Stack<>();//中间栈
16             while(!stack.isEmpty()){
17                 String string = stack.pop();
18                 //运算符直接进栈
19                 if(string.equals("+")||string.equals("-")||string.equals("*")||string.equals("÷")){
20                     Calcul_Expression calcul_exp = new Calcul_Expression(true,string);
21                     stack1.push(calcul_exp);
22                 }
23                 else if(!string.contains("/")){
24                     string = string + "/1";
25                     Calcul_Expression node = new Calcul_Expression(false,string);
26                     stack1.push(node);
27                 }
28                 else {
29                     Calcul_Expression calculator = new Calcul_Expression(false,string);
30                     stack1.push(calculator);
31                 }
32             }
33             for(Calcul_Expression c:stack1){
34                 stack2.push(c);
35             }
36             this.posfixStack = stack2;
37 
38         }
39     
40 
41 }

 

4、表达式计算
  1 package Calculation;
  2 
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.Stack;
  6 
  7 public class Calcul_Expression {    //计算表达式
  8 
  9 
 10         
 11         private static final int String = 0;
 12         Integer fenzi;//分子
 13         Integer fenmu;//分母
 14         boolean isysf;
 15         String ysf;
 16         Calcul_Expression lChild;
 17         Calcul_Expression rChild;
 18         
 19         
 20         //运算符构造方法 
 21         public Calcul_Expression(boolean isysf,Integer num,Integer den) {
 22             this.isysf = isysf;
 23             this.fenmu = den;
 24             this.fenzi = num;
 25             
 26         }
 27         
 28         public Calcul_Expression(boolean isysf,String stackElement) {
 29             if(isysf == true){//为运算符
 30                 this.isysf = true;
 31                 this.ysf = stackElement;    
 32             }
 33             else if (isysf == false && stackElement.contains("'")){//为带分数
 34                 String[] split1 = stackElement.split("'");
 35                 String[] split2 = split1[1].split("\\/");
 36                 this.fenzi = Integer.parseInt(split1[0])*Integer.parseInt(split2[1]) 
 37                         + Integer.parseInt(split2[0]);
 38                 this.fenmu = Integer.parseInt(split2[1]);
 39             }
 40             else if(isysf == false && (!stackElement.contains("'"))){//为分数
 41                 String[] s = stackElement.split("\\/");
 42                 this.fenzi = Integer.parseInt(s[0]);
 43                 this.fenmu = Integer.parseInt(s[1]);
 44             }
 45         }
 46         
 47     
 48         
 49         public Calcul_Expression() {
 50         }
 51         
 52         //根据后缀表达式(分子分母形式)计算
 53         //返回运算结果存于stack2中
 54         public Stack<Calcul_Expression> calculate(Stack<Calcul_Expression> stackOld){
 55             Stack<Calcul_Expression> stack=(Stack<Calcul_Expression>) stackOld.clone();
 56             Stack<Calcul_Expression> stack2 = new Stack<>();
 57             Calcul_Expression calculator;
 58             while(!stack.isEmpty()){
 59                 if(!(calculator = stack.pop()).isysf){//操作数直接入栈
 60                     stack2.push(calculator);
 61                 }
 62                 else  if(calculator.isysf){//若为运算符
 63                     
 64                     //每次去除栈顶两个元素
 65                     Calcul_Expression calculator1 = stack2.pop();
 66                     Calcul_Expression calculator2 = stack2.pop();
 67                     
 68                     switch (calculator.ysf) {
 69                     case "+":
 70                         stack2.push(calculator.add(calculator2, calculator1));
 71                         break;
 72                         
 73                     case "-":
 74                         Calcul_Expression res=calculator.sub(calculator2, calculator1);
 75                         if(res.fenzi>0){
 76                             stack2.push(res);
 77                         }else{
 78                             res.ysf="#";
 79                             stack2.push(res);
 80                             return stack2;
 81                         }
 82                         stack2.push(calculator.sub(calculator2, calculator1));
 83                         break;
 84                         
 85                     case "*":
 86                         stack2.push(calculator.mul(calculator2, calculator1));
 87                         break;
 88                         
 89                     case "÷":
 90                         stack2.push(calculator.div(calculator2, calculator1));
 91                         break;
 92         
 93                     default:
 94                         break;
 95                     }
 96                     
 97                 }
 98             }
 99             return stack2;
100         }
101         
102         //加法
103         public Calcul_Expression add(Calcul_Expression calculator1,Calcul_Expression calculator2) {
104             Integer num = calculator1.fenzi*calculator2.fenmu +
105                     calculator2.fenzi*calculator1.fenmu;
106                     Integer den = calculator1.fenmu*calculator2.fenmu;
107                     int g = gcd(num, den);
108                     Calcul_Expression calculator = new Calcul_Expression(false, num/g, den/g);
109                     return calculator;
110         }
111         
112         //减法
113         public Calcul_Expression sub(Calcul_Expression calculator1,Calcul_Expression calculator2) {
114             Integer num = calculator1.fenzi*calculator2.fenmu -
115                     calculator2.fenzi*calculator1.fenmu;
116             Integer den = calculator1.fenmu*calculator2.fenmu;
117             int g = gcd(num, den);
118             Calcul_Expression calculator = new Calcul_Expression(false, num/g, den/g);
119             return calculator;
120         }
121         
122         //乘法
123         public Calcul_Expression mul(Calcul_Expression calculator1,Calcul_Expression calculator2) {
124             Integer num = calculator1.fenzi*calculator2.fenzi;
125             Integer den = calculator1.fenmu*calculator2.fenmu;
126             int g = gcd(num, den);
127             Calcul_Expression calculator = new Calcul_Expression(false, num/g, den/g);
128             return calculator;
129         }
130         
131         //除法
132         public Calcul_Expression div(Calcul_Expression calculator1,Calcul_Expression calculator2) {
133             Integer num = calculator1.fenzi*calculator2.fenmu;
134             Integer den = calculator1.fenmu*calculator2.fenzi;
135             int g = gcd(num, den);
136             Calcul_Expression calculator = new Calcul_Expression(false, num/g, den/g);
137             return calculator;
138         }
139         
140         //最大公约数
141         public int gcd(int a, int b){
142             int m = Math.max(Math.abs(a), Math.abs(b));
143             int n = Math.min(Math.abs(a), Math.abs(b));
144             int r;
145             while(n!=0){
146                 r = m % n;
147                 m = n;
148                 n = r;
149             }
150             return m;
151         }
152         
153         //比较两个分数数大小
154         /**
155          * 
156          * @return     f1 > f2 返回 2
157          *             f1 = f2返回1
158          *             f1 < f2返回-1
159          *             其他 返回0
160          */
161         public int compareFraction(Calcul_Expression f1,Calcul_Expression f2) {
162             Calcul_Expression node = new Calcul_Expression();
163                     
164             if (f1.isysf||f2.isysf) {
165                 System.out.println("请输入数字进行比较!");
166                 return 0;
167             }
168             Calcul_Expression compare = node.sub(f1, f2);//f1 - f2 结果为Calcul_Expression类型
169             int result = compare.fenzi/compare.fenmu;//f1 - f2的结果
170             if (result == 0) {
171                 return 1;
172             }
173             else if (result > 0) {
174                 return 2;
175             }
176             else if (result < 0) {
177                 return -1;
178             } 
179                 
180             return 0;
181         }
182         
183         /**
184          * 
185          * @param o1
186          * @param o2
187          * @return     o1 > o2 return 2
188          *             o1 = o2 return 1
189          *             o1 < o2 return -1
190          *             其他                 return 0
191          */
192         public int  compareysf(Calcul_Expression o1,Calcul_Expression o2) {
193             if (!o1.isysf||!o2.isysf) {
194                 System.out.println("请输入正确运算符!");
195                 return 0;
196             }
197             HashMap<String, Integer> priMap = new HashMap<>();
198             priMap.put("+", 0);
199             priMap.put("-", 0);
200             priMap.put("*", 1);
201             priMap.put("÷", 1);
202             
203             if (priMap.get(o1.ysf) > priMap.get(o2.ysf)) {
204                 //o1 高于 o2
205                 return 2;
206             }
207             else if (priMap.get(o1.ysf) == priMap.get(o2.ysf)) {
208                 //o1 低于o2
209                 return 1;
210             }
211             else if (priMap.get(o1.ysf) < priMap.get(o2.ysf)) {
212                 //o1等于o2
213                 return 1;
214             }
215             return 0;
216         }
217         
218         //假分数转带分数输出
219             public ArrayList<String> imTomix(ArrayList<Calcul_Expression> answerList) {
220                 ArrayList<String> arrayList = new ArrayList<>();
221                 for (int i = 0; i < answerList.size(); i++) {
222                     if (answerList.get(i).isysf) {
223                         System.out.println("这个结果算错了!");
224                     }
225                     else if (answerList.get(i).fenmu == 1){//分母为1,分数= 分子的值
226                         arrayList.add(answerList.get(i).fenzi + "");
227                     }
228                     else if ((answerList.get(i).fenzi == 0) ||(answerList.get(i).fenzi == 0)) {//若分子为0,则分数为0
229                         arrayList.add(answerList.get(i).fenzi + "");
230                     }
231                     else if (answerList.get(i).fenzi == answerList.get(i).fenmu) {//分子等于分母,answer=1
232                         arrayList.add(1+"");
233                     }
234                     else if (answerList.get(i).fenzi%answerList.get(i).fenmu == 0) {//分子能整除分母
235                         arrayList.add(answerList.get(i).fenzi/answerList.get(i).fenmu + "");
236                     } 
237                     else if((answerList.get(i).fenmu!=0)&&answerList.get(i).fenzi/answerList.get(i).fenmu> 1) {//假分数,转带分数
238                         arrayList.add(answerList.get(i).fenzi/answerList.get(i).fenmu + "'" 
239                                 + answerList.get(i).fenzi%answerList.get(i).fenmu + "/" + answerList.get(i).fenmu);
240                     }
241                     else {
242                         arrayList.add(answerList.get(i).fenzi + "/" + answerList.get(i).fenmu + "");
243                     }
244                 }
245                 return arrayList;
246             }
247         
248         
249     
250 
251 }

 

5、检查重复
  1 package Calculation;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Stack;
  5 
  6 /**
  7  * 构造方法:生成查重表达式
  8  * @author LHY
  9  *
 10  */
 11 public class Repeat {
 12     /**
 13      * @param profixStack 后缀表达式栈
 14      */
 15     public Stack<Calcul_Expression> checkRepeat(Stack<Calcul_Expression> profixStack) {
 16         // TODO Auto-generated constructor stub
 17         Stack<Calcul_Expression> numberStack = new Stack<>(); //构造一个中间栈,存放数字
 18         Stack<Calcul_Expression> checkStack = new Stack<>(); //存放查重表达式栈
 19                 
 20 //        System.out.println(1);
 21         Calcul_Expression bookNode = new Calcul_Expression(true, 0,0);
 22 //        System.out.println(2);
 23         Calcul_Expression node1 = new Calcul_Expression();
 24         Calcul_Expression node2 = new Calcul_Expression();
 25         while(!profixStack.isEmpty()){//扫描后缀表达式栈直至其为空
 26             Calcul_Expression proStack_top = profixStack.pop();//开始扫描第一个
 27             if (!proStack_top.isysf&&!(proStack_top.fenzi==0&&proStack_top.fenmu==0)) {//若后缀表达式栈顶元素为数字。若非#则进numberStack
 28                     numberStack.push(proStack_top);
 29 //                    System.out.println(proStack_top);
 30             }
 31 //            else if (proStack_top.isOperator&&proStack_top.numerator==0&&proStack_top.denominator==0) {
 32 //                numberStack.pop();
 33 //            }
 34             else if (proStack_top.isysf) {//后缀表达式栈顶为运算符,则进checkStack,再pop两个数字,并把#压进数字
 35                 checkStack.push(proStack_top);
 36                 if (numberStack.size() > 1) {
 37                     if (!(node1=numberStack.pop()).isysf&&!(node1.fenzi==0)&&!(node1.fenmu==0)) {//非#
 38                         checkStack.push(node1);
 39                     }
 40                     if (!(node2=numberStack.pop()).isysf&&!(node2.fenzi==0)&&!(node2.fenmu==0)) {
 41                         checkStack.push(node2);
 42                     }
 43                 }
 44                 numberStack.push(bookNode);
 45             }
 46             
 47         }//end while
 48         System.out.println("size"+checkStack.size());
 49         for(Calcul_Expression node:checkStack){
 50             if (node.isysf) {
 51                 System.out.print(node.ysf + " ");
 52             }else if(!node.isysf){
 53                 System.out.print(node.fenzi + "/" + node.fenmu + " ");
 54             }
 55         }
 56         return checkStack;
 57         
 58     }
 59     
 60     public  boolean IsRepeat(Stack<Calcul_Expression> exp1,Stack<Calcul_Expression> exp2){
 61         Repeat repeat=new Repeat();
 62         //转成查重表达式
 63         ArrayList<Calcul_Expression> temp=new ArrayList<Calcul_Expression>();//中间存放栈1
 64         Calcul_Expression tempNode=new Calcul_Expression();//中间交换结点
 65         Stack<Calcul_Expression> checkRepeat1=repeat.checkRepeat(exp1);
 66         Stack<Calcul_Expression> checkRepeat2=repeat.checkRepeat(exp2);
 67         Stack<Calcul_Expression> newStack=new Stack<Calcul_Expression>();//交换后的新栈
 68         int lengthRe1=checkRepeat1.size();
 69         int lengthRe2=checkRepeat2.size();
 70         System.out.println(1);
 71         if(lengthRe1!=lengthRe2) return false;//若长度不相等,则表达式一定不同
 72         System.out.println(2);
 73         for(Calcul_Expression n:checkRepeat1){
 74             temp.add(n);
 75         }
 76         if (this.isEqual(checkRepeat1, checkRepeat2)) {//完全一样则返回true
 77             return true;
 78         }
 79 
 80         if(temp.get(0).ysf.equals("+")||temp.get(0).ysf.equals("*")){//只有加或乘的情况才可能出现 交换左右操作数当做重复的表达式
 81             tempNode=temp.get(1);
 82             temp.set(1, temp.get(2));
 83             temp.set(2, tempNode);
 84         }
 85         for(Calcul_Expression p:temp){
 86             newStack.push(p);
 87         }
 88         if(this.isEqual(newStack, checkRepeat2)) return true;//若交换后也相等则重复
 89         System.out.println(3);
 90         return false;
 91     }
 92     
 93     public boolean  isEqual(Stack<Calcul_Expression> stack1,Stack<Calcul_Expression> stack2) {
 94         Stack<Calcul_Expression> s1 = new Stack<>();
 95         Stack<Calcul_Expression> s2 = new Stack<>();
 96         
 97         Calcul_Expression s1_top;
 98         Calcul_Expression s2_top;
 99         for(Calcul_Expression node1:stack1){
100             s1.push(node1);
101         }
102         for(Calcul_Expression node2:stack2){
103             s2.push(node2);
104         }
105         
106         while (!s1.isEmpty()&&!s2.isEmpty()) {
107             s1_top = s1.pop();
108             s2_top = s2.pop();
109             if (s1_top.isysf) {//若s1栈顶为运算符
110                 if (s2_top.isysf&&(!s2_top.ysf.equals(s1_top.ysf))) {//s2都为运算符但s1不等于s2
111                     return false;
112                 }
113                 else if (!s2_top.isysf) {//s1为运算符,s2非运算符
114                     return false;
115                 }
116             }
117             else if (!s1_top.isysf) {//若s1操作数
118                 if (s2_top.isysf) {//s2为运算符
119                     return false;
120                 }
121                 else if (!s2_top.isysf&&(s2_top.compareFraction(s1_top, s2_top)!=1)) {//s2为操作数但不等于s1
122                 return false;    
123                 }
124             }
125             
126         }        
127         return true;
128     }
129 }

 

 
6、满足非负及非重复条件生成表达式
int count=0;
                ArrayList<String> finalExp=new ArrayList<>();//最终所有表达式
                ArrayList<Calcul_Expression> finalRes=new ArrayList<>();//最终所有结果(假分数)
                ArrayList<String> realRes =new ArrayList<>();//最终所有结果(真分数)
                ArrayList<Stack<Calcul_Expression>> checkArray=new ArrayList<>();//查重存放数组
                Repeat repeat=new Repeat();
                
                do {
                    boolean flag=false;
                    Stack<String> ac=new Stack<String>();
                    ac=After_Expression.toAfter_Expression(Ran_Expression.creatAc(range));//没带分母的后缀表达式
                    CaoZuoShu_handle handle=new CaoZuoShu_handle(ac);//带分母的后缀表达式
                    Calcul_Expression node=new Calcul_Expression();
                    Stack<Calcul_Expression> stack=new Stack<Calcul_Expression>();
                    stack=node.calculate(handle.posfixStack);//计算结果
                    if(stack.peek().ysf!="#"&&count==0){//非负,第一个表达式
                        checkArray.add(handle.posfixStack);
                        finalExp.add(Ran_Expression.exp_str);
                        finalRes.add(stack.peek());
                        count++;
                    }
                    if(stack.peek().ysf!="#"&&count>0){//非负,第二个表达式开始
                        for(Stack<Calcul_Expression> p:checkArray){
                            
                            if(repeat.isEqual(p, handle.posfixStack)){
                                flag=true;
                            }
                        }
                        if(!flag){
                            checkArray.add(handle.posfixStack);
                            finalExp.add(Ran_Expression.exp_str);
                            finalRes.add(stack.peek());
                            count++;
                        }
                    }
                } while (count!=number);
                Calcul_Expression transNode=new Calcul_Expression();
                realRes=transNode.imTomix(finalRes);
                
                for (int i = 0; i < finalExp.size(); i++) {
                    System.out.println("第"+i+"题:"+finalExp.get(i));
                }
                for (int i = 0; i < realRes.size(); i++) {
                    System.out.println("第"+i+"题答案:"+realRes.get(i));
                }
                System.out.println("答案真正长度"+finalRes.size());    

 

 
 
7、文件读取
package Calculation;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;

import javax.imageio.spi.RegisterableService;


public class FileRW {

    /**
     * 将题目和答案写出在txt文件中
     * @param expList 题目集合
      * @param answerList 答案集合
     * @return  true 成功
     *             false 失败
     */
    public boolean fileWrite(ArrayList<String> expList,ArrayList<Calcul_Expression> answerList) {
        ArrayList<String>  outList = new ArrayList<>();    
        if (expList.size()!=answerList.size()) {
            System.out.println("答案与题目数目不匹配!");
            return false;
        }
        
        for (int i = 0; i < expList.size(); i++) {
            System.out.println();
            outList.add(expList.get(i) + " = " +answerList.get(i).fenzi + "/"+ answerList.get(i).fenmu);
        }
        //开始写入文件
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
            for(String s:outList){
                bw.write(s);
                bw.newLine();
                bw.flush();
            }
            bw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return true;
    }
    
    /**
     * 把题目写出到文件
     * @param expList 
     * @return
     */
    public File writeQ(ArrayList<String> expList) {
        int count = 1;
        File file = new File("Question.txt");
            try {
                FileWriter fWriter = new FileWriter(file);
                BufferedWriter bw = new BufferedWriter(fWriter);
                for(String s:expList){
                    bw.write( count++ + "." +s);
                    bw.newLine();
                    bw.flush();
                }
                bw.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return file;
    }
    
    /**
     * 把答案写出到文件
     * @param answerList
     * @return
     * @throws IOException 
     */
    public File writeA(ArrayList<String> answerList) throws IOException {
        int count = 1;
        File file = new File("Answer.txt");
        FileWriter fWriter = new FileWriter(file);
        try {
            BufferedWriter bw = new BufferedWriter(fWriter);
            for(String s:answerList){
                bw.write( count++ + "." +s);
                bw.newLine();
                bw.flush();
            }
            bw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return file;
    }
    
    
/**
 * 
 * @param answerFile 待检测文件
 * @param answerList 正确答案文件
 * @return
 */
    public File checkAnswer(File answerFile,File answerList) {

        try {
            BufferedReader rightReader = new BufferedReader(new FileReader(answerList));
            BufferedReader anserReader = new BufferedReader(new FileReader(answerFile));
            String rightString = null;
            String answerString = null;
            int right = 0;
            int wrong = 0; 
            int line = 1;
            
            String Rnumber="";
            String Wnumber="";
            //比较对错
            while((rightString=rightReader.readLine())!=null&&(answerString=anserReader.readLine())!=null){
                if(rightString.equals(answerString)){
                    right ++;
                    if (Rnumber.equals("")) {
                        Rnumber = Rnumber +line;
                    }
                    else{
                        Rnumber = Rnumber + ","+line;
                    }
                }
                else {
                    System.out.println(rightString);
                    System.out.println(answerString);
                    wrong++;
                    if (Wnumber.equals("")) {
                        Wnumber = Wnumber +line;
                    }else{
                        Wnumber = Wnumber + "," +line;
                    }
                }
                line++;
            }
            
            //写入到answerfile中
            BufferedWriter bw = new BufferedWriter(new FileWriter(answerFile, true));
            bw.newLine();
            bw.write("right: "+ right + " " + "("+ Rnumber +")" + ";");
            bw.newLine();
            bw.write("wrong: "+ wrong + " " + "("+ Wnumber + ")"+ ";");
            bw.flush();
            bw.close();
            
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return answerFile;
        
    }
    
}
 
 
 
五、测试截图

 

 

 

 

 代码覆盖率:

 

 

 

 

 

 
 
 
 
六、PSP时间统计

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

45 

47

· Estimate

· 估计这个任务需要多少时间

45

47

Development

开发

1405

1492 

· Analysis

· 需求分析 (包括学习新技术)

80 

95

· Design Spec

· 生成设计文档

40 

36 

· Design Review

· 设计复审 (和同事审核设计文档)

45 

55 

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

35 

30

· Design

· 具体设计

120 

107 

· Coding

· 具体编码

960 

1050 

· Code Review

· 代码复审

50 

35 

· Test

· 测试(自我测试,修改代码,提交修改)

75 

84 

Reporting

报告

180 

235 

· Test Report

· 测试报告

120 

180 

· Size Measurement

· 计算工作量

20 

20

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

40 

35 

合计

 

1630

1774 

 
 
七、项目总结

  这次结对编程项目相比上次的个人项目,整体的完成过程要更为复杂一些,也更加耗时间。做个人项目的时候,可以自己按照自己整体的代码构架和实现思路去走,在类的创建和实现上,也比较自由。而本次结对编程,就要求我们在团队协作这一块上一定要做得好,两个人一起实现同一个项目并不是一件简单的事情。我们在一开始对项目设计的讨论中,由于没有很明确地达成一致的思路,可以说只是商定了一个大概的框架,所以真正在分工实现项目的过程中,难免出现了一些问题,在最后联结双方的项目工程时发现无法完全契合双方的各种实现类。于是,在经过第二轮的讨论交流和实践修改后,才得以完成本次结对编程项目,这让我们都意识到小组交流和相互更新进度这些合作事宜的重要性。这次项目也让我们两个人从中学到了很多,明确了彼此的一些知识盲区,相信有了结对编程的经验后,在后续的团队编程项目中我们会做得更好。

 
 

posted on 2019-10-17 01:32  灵儿102  阅读(268)  评论(0编辑  收藏  举报

导航