软件工程第三次作业 结对编程

结对编程

小组成员:

201521123055 林一心 博客地址

201521123046 张杭镖 博客地址

项目地址

一、分析改进现有代码

1.单元测试:

2.覆盖率:

3.确定当前设计的一个弱点,通过重构,确保在这个地方已有测试覆盖并保证重构没有改变已有的功能:

原程序只能生成两个数之间的算式,并且分数与整数算式出现几率没设置正确。

4.修改代码后,检查代码覆盖,看单元测试是否需要修改?测试用例是否需要增加?

单元测试需要修改,因为添加了多个数字的运算。

二、功能扩展

增加了括号运算符,相应的计算函数也要添加括号运算符的处理,原代码把计算过程放在main生成算式的main类中处理,扩展功能后代码显得臃肿,因此单独把计算功能拉出来做一个Calculator类。(这个计算功能同样也支持多位整数的计算,以便小学生升级到进阶地狱)

核心代码:

生成题目

		
	public main()//生成四则运算并输出
	{
		new Thread(myTimeRunable).start();
		int n = 0;
		MainFrame ma= new MainFrame();


		try{
			//调用初始化方法
			jbInit();
		}
		catch(Exception exception){
			exception.printStackTrace();
		}

		try{

			n= Integer.parseInt(ma.number);

			}catch(NumberFormatException e){
				//利用消息对话框提示输入失败
				JOptionPane.showMessageDialog(this,"输入错误!请重新输入");
				}

			int m = (int)(Math.random()*n+1);//随机整数题目和分数题目的题量

			for(int j=0;j<(n-m);j++){//整数题目
				int no=(int)(Math.random()*3+1); //最多四个数字运算
				StringBuffer qustr=new StringBuffer("");
				String ans;
				int numm=(int)(Math.random()*9+1);//随机数字

				qustr.append(numm);

				for(int i=0;i<no;i++){
					numm=(int)(Math.random()*9+1);
					int op=(int)(Math.random()*4+1);//随机选择计算符

					if(op==1){//加法
						qustr.append("+"+numm);
						//Answer.add(num1+num2+"");
					}
					if(op==2){
						qustr.append("-"+numm);
					}

					if(op==3){//乘法
						qustr.append("*"+numm);
					}
					if(op==4){//除法
						i--;
						continue;
					}
				}
				if(no>=2) {
					int left_kuo = (int) (Math.random() * no  + 1);
					int right_kuo = (int) (Math.random() * (no+1 - left_kuo) + 1 + left_kuo);
					qustr.insert(2*(left_kuo-1), '(');
					qustr.insert(2*right_kuo, ')');
				}
				qustr.append('=');
				Question.add(qustr.toString());
				Calculator cal=new Calculator();
				Answer.add(""+cal.caculate(qustr.toString()));
			}







        for(int j=0;j<m;j++){//分数题目
    		   Scanner in = new Scanner(System.in);//真分数的计算
    		   int op=(int)(Math.random()*4+1);
    		   int[] f1 =createFraction();
    	       int[] f2 =createFraction();
    	       int j1=GCD(f1[0],f1[1]);
    	       f1[0]=f1[0]/j1;//化简分数
    	       f1[1]=f1[1]/j1;
    	       j1=GCD(f2[0],f2[1]);
    	       f2[0]=f2[0]/j1;
    	       f2[1]=f2[1]/j1;
    	       int gbs = LCM(f1[1],f2[1]);

        	 if(op==1){//加法
        		  Question.add("("+f1[0]+"/"+f1[1]+")+("+f2[0]+"/"+f2[1]+")=");
    	          int num1=f1[0]*f2[1]+f2[0]*f1[1];
    	          int num2=f1[1]*f2[1];
    	          int num3=GCD(num1,num2);
    	          num1=num1/num3;
    	          num2=num2/num3;
    			  String a=new String();
    			  if(num1==num2)
    	            {
    	                a="1";
    	            }
    	            else {
					  a = num1 + "/" + num2;
				  }
    			  Answer.add(a+"");

    		  }
    		   if(op==2){//减法
    			   int num1=f1[0]*f2[1]-f2[0]*f1[1];
    			   if(num1>0){  //防止出现负数
    				 Question.add("("+f1[0]+"/"+f1[1]+")-("+f2[0]+"/"+f2[1]+")=");
    				 int num2=f1[1]*f2[1];
    				 String a=new String();
    				 if(num1==0)
    	                {
    	                    a="0";
    	                }
    	                else
    	                {
    	                int num3=Math.abs(GCD(num1,num2));
    		            num1=num1/num3;
    		            num2=num2/num3;
    	                if(num1==num2)
    	                {
    	                    a="1";
    	                }
    	                else
    	                {
    	                    a=num1+"/"+num2;
    	                }
    	                }
    				 Answer.add(a+"");
    		   }else{
    			   Question.add("("+f2[0]+"/"+f2[1]+")-("+f1[0]+"/"+f1[1]+")=");
    			     int num11=f2[0]*f1[1]-f1[0]*f2[1];
    				 int num2=f1[1]*f2[1];
    				 String a=new String();
    				 if(num11==0)
    	                {
    	                    a="0";
    	                }
    	                else
    	                {
							int num3=Math.abs(GCD(num11,num2));
							num11=num11/num3;
							num2=num2/num3;
							if(num11==num2)
							{
								a="1";
							}
							else
							{
								a=num11+"/"+num2;
							}
    	                }
    				  Answer.add(a+"");



    		   }
    			  }
    		  if(op==3){//乘法
    			     Question.add("("+f1[0]+"/"+f1[1]+")*("+f2[0]+"/"+f2[1]+")=");
    				 int num1= f1[0]*f2[0];
                     int num2 = f1[1]*f2[1];
    				 int num3=GCD(num1,num2);
    				 String a=new String();
    				 num1= num1/num3;
                     num2 = num2/num3;
                  if(num1==num2)
    	                {
    	                    a="1";
    	                }
    	                else
    	                {
    	                    a=num1+"/"+num2;
    	                }
                     Answer.add(a+"");
    			  }
    		  if(op==4){//除法
    			     Question.add("("+f1[0]+"/"+f1[1]+")÷("+f2[0]+"/"+f2[1]+")=");
    				 int num1= f1[0]*f2[1];
    				 int num2 = f1[1]*f2[0];
    				 int num3=GCD(num1,num2);
    				 String a=new String();
    				 num1= num1/num3;
                     num2 = num2/num3;
                     if(num1==num2)
    	                {
    	                    a="1";
    	                }
    	                else
    	                {
    	                    a=num1+"/"+num2;
    	                }
                     Answer.add(a+"");
    		  }
        }

        //输出题目
        JTextArea0.setText("");
        for(String string : Question){
            num ++;
            JTextArea0.append("("+num+")、"+string+"\n");
        }
	}

计算

   	public class Calculator {


				private Stack<Long> numberStack = null;

				private Stack<Character> symbolStack = null;

				
				public long caculate(String numStr) {


					// 初始化栈
					numberStack = new Stack<Long>();
					symbolStack = new Stack<Character>();
					// 用于缓存数字,因为数字可能是多位的
					StringBuffer temp = new StringBuffer();
					// 从表达式的第一个字符开始处理
					for (int i = 0; i < numStr.length(); i++) {
						char ch = numStr.charAt(i); // 获取一个字符
						if (isNumber(ch)) { // 若当前字符是数字
							temp.append(ch); // 加入到数字缓存中
						} else { // 非数字的情况
							String tempStr = temp.toString(); // 将数字缓存转为字符串
							if (!tempStr.isEmpty()) {
								long num = Long.parseLong(tempStr); // 将数字字符串转为长整型数
								numberStack.push(num); // 将数字压栈
								temp = new StringBuffer(); // 重置数字缓存
							}
							// 判断运算符的优先级,若当前优先级低于栈顶的优先级,则先把计算前面计算出来
							while (!comparePri(ch) && !symbolStack.empty()) {
								long b = numberStack.pop(); // 出栈,取出数字,后进先出
								long a = numberStack.pop();
								// 取出运算符进行相应运算,并把结果压栈进行下一次运算
								switch ((char) symbolStack.pop()) {
									case '+':
										numberStack.push(a + b);
										break;
									case '-':
										numberStack.push(a - b);
										break;
									case '*':
										numberStack.push(a * b);
										break;
									case '/':
										numberStack.push(a / b);
										break;
									default:
										break;
								}
							} // while循环结束
							if (ch != '=') {
								symbolStack.push(new Character(ch)); // 符号入栈
								if (ch == ')') { // 去括号
									symbolStack.pop();
									symbolStack.pop();
								}
							}
						}
					} // for循环结束

					return numberStack.pop(); // 返回计算结果
				}

			
				private String removeStrSpace(String str) {
					return str != null ? str.replaceAll(" ", "") : "";
				}

				private boolean isStandard(String numStr) {
					if (numStr == null || numStr.isEmpty()) // 表达式不能为空
						return false;
					Stack<Character> stack = new Stack<Character>(); // 用来保存括号,检查左右括号是否匹配
					boolean b = false; // 用来标记'='符号是否存在多个
					for (int i = 0; i < numStr.length(); i++) {
						char n = numStr.charAt(i);
						// 判断字符是否合法
						if (!(isNumber(n) || "(".equals(n + "") || ")".equals(n + "")
								|| "+".equals(n + "") || "-".equals(n + "")
								|| "*".equals(n + "") || "/".equals(n + "")
								|| "=".equals(n + ""))) {
							return false;
						}
						// 将左括号压栈,用来给后面的右括号进行匹配
						if ("(".equals(n + "")) {
							stack.push(n);
						}
						if (")".equals(n + "")) { // 匹配括号
							if (stack.isEmpty() || !"(".equals((char) stack.pop() + "")) // 括号是否匹配
								return false;
						}
						// 检查是否有多个'='号
						if ("=".equals(n + "")) {
							if (b)
								return false;
							b = true;
						}
					}
					// 可能会有缺少右括号的情况
					if (!stack.isEmpty())
						return false;
					// 检查'='号是否不在末尾
					if (!("=".equals(numStr.charAt(numStr.length() - 1) + "")))
						return false;
					return true;
				}

			
				private boolean isNumber(char num) {
					if (num >= '0' && num <= '9')
						return true;
					return false;
				}

				
				private boolean comparePri(char symbol) {
					if (symbolStack.empty()) { // 空栈返回ture
						return true;
					}


					char top = (char) symbolStack.peek();
					if (top == '(') {
						return true;
					}
					// 比较优先级
					switch (symbol) {
						case '(': // 优先级最高
							return true;
						case '*': {
							if (top == '+' || top == '-') // 优先级比+和-高
								return true;
							else
								return false;
						}
						case '/': {
							if (top == '+' || top == '-') // 优先级比+和-高
								return true;
							else
								return false;
						}
						case '+':
							return false;
						case '-':
							return false;
						case ')': // 优先级最低
							return false;
						case '=': // 结束符
							return false;
						default:
							break;
					}
					return true;
				}


			}
		

运行结果:

效能分析:

三、小结感受

结队编程在大二学习JAVA时有尝试过,只是初步体验了一下,这次与大佬结队希望真的能够学到东西提升自己,有个领航员,可以时刻发现问题。两人一起寻找问题发现问题感觉效率比较高,但编程过程还是比较坎坷,希望最后能够一加一大于二,乃至远大于二。

PSP2.1 个人开发流程 预估耗费时间(分钟) 实际耗费时间(分钟)
Planning 计划 15 8
Estimate 明确需求和其他相关因素,估计每个阶段的时间成本 10 4
Development 开发 120 140
Analysis 需求分析需求分析 (包括学习新技术) 10 10
Design Spec 生成设计文档 0 0
Design Review 设计复审 10 8
Coding Standard 代码规范 2 2
Design 具体设计 10 15
Coding 具体编码 40 60
Code Review 代码复审 20 10
Test 测试(自我测试,修改代码,提交修改) 15 15
Reporting 报告 15 12
· 测试报告 2 2
· 计算工作量 15 10
· 并提出过程改进计划 10 5
posted @ 2018-03-25 20:51  阿鏢  阅读(148)  评论(0编辑  收藏  举报