软工实践寒假作业(2/2)

软工实践寒假作业(2/2)

这个作业属于哪个课程 2020春丨S班 (福州大学)
这个作业要求在哪里 软工实践寒假作业(2/2)
这个作业的目标 学习使用github,规范代码,java指令的解析,java字符串处理,代码测试
作业正文 我的作业
其他参考文献 《阿里巴巴JAVA开发手册》源代码管理Commit message 和 Change log 编写指南Java 正则表达式单元测试 & 回归测试寒假第二次作业引导和提示

Github仓库地址

shodowQAQ/InfectStatistic-main

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 40
Estimate 估计这个任务需要多少时间 60 40
Development 开发 600 900
Analysis 需求分析 (包括学习新技术) 120 100
Design Spec 生成设计文档 120 80
Design Review 设计复审 60 40
Coding Standard 代码规范 (为目前的开发制定合适的规范) 60 30
Design 具体设计 120 100
Coding 具体编码 480 560
Code Review 代码复审 60 40
Test 测试(自我测试,修改代码,提交修改) 60 50
Reporting 报告 60 60
Test Repor 测试报告 60 40
Size Measurement 计算工作量 40 30
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 30
合计 1870 2140

解题思路

题目可以分为三部分:1.指令分解   2.文件的读写   3.字符串的处理
	大前提: 
	先定好需要输出的数据。如:省份名字,每个省份有四种人,就定个二维数组与省份对应等等。
	再定义标记数据。如:每个省份一个标记,判断该省份是否需要输出。
	1.首先是指令分解:
	有一说一这个真的难倒我了,以前写的java程序都是用的swing,写c++程序的界面也是用的 switch()不断刷新界面,第一次写这种需要拆分指令的程序。刚开始没思路,本来打算直接输入一个String然后对String进行解析。后来觉得这样做太复杂问了同学,同学给了他的解决思路,才改用现在的思路。即使用args生成的String[],有一个好处是用空格可以指令分开,这样就大大的简化了对指令的处理,把指令拆分开来进行对比。
	首先是匹配-list,-date,-log,-out,这些指令。当匹配到这些指令之后在对这些指令后面的内容进行处理,判断输入的信息是否正确,符合要求。
	2.文件的读写:
	文件的读就是对日期进行比较,选择要读取的文件。
	文件的写首先是基础版,即不带-province或-type,只要把所有的province的二维数组写出配合文字即可。
	升级版就是给每一个type和province都建立一个与之对应的数组,当数组的值为0时写出,为1的时候掠过。
	3.字符串的处理
	这部分有用的正则表达式和字符串的函数,从文本中提取数字,判断文本的类型。
GitHub

设计实现过程

1.基础数据
	/*定义静态数据省份和数据*/
	static String[] province = {"全国", "安徽", "澳门" ,"北京", "重庆", "福建","甘肃","广东", "广西", "贵州", "海南", "河北", "河南", "黑龙江", "湖北", "湖南", "吉林","江苏", "江西", "辽宁", "内蒙古", "宁夏", "青海", "山东", "山西", "陕西", "上海","四川", "台湾", "天津", "西藏", "香港", "新疆", "云南", "浙江"};
	/*定义每个省份的四种数据*/
	static int[][] data =new int[35][4];
	/*定义需要输出的省份默认全为零即全输出*/
	static int[] needprovince=new int[35];
	/*定义时间*/
	static String date;
	/*定义输入路径*/
	static String input;
	/*定义输出路径*/
	static String output;
	/*定义需要输出的类型默认全为零即全输出*/
	static int[] type = new int[4];
	/*定义患者类型*/
	static String[] typename = {"感染患者", "疑似患者", "治愈", "死亡"};
	
2.指令分解:
	指令保存为String[] args,对每个args[i]判断,对于每种判断结果有不同的操作,-out和-log都对指令的值进行正则表达式匹配,然后值赋给output和input变量。-type对ip,sp,cure,dead进行匹配对type[]进行赋值,为0输出为1不输出。-province 对省份名字进行匹配,同样为零输出,为一不输出。
GitHub
3.文件读取
	在input路径下,先读入要读取的文件名称,对每个文件的每行进行读取,对每行的内容进行正则表达式匹配,当读到不同内容时进行不同处理,就是对int[][] data的数据进行加减,这部分简单,只要表达式判断正确就可以。
GitHub
4.文件写入
	我首先完成的是对所有的省份和类型的人都写入。只要省份加类型加数据写入就可以。
	然后增加了-province和-type属性,在输出前对type[],和needprovince[]进行判断就可以。
GitHub

代码说明

判断指令:
	因为指令为String[],对指令进行匹配,匹配到相应的字符串就进行指令处理。处理结束后i++跳转到下一个指令。
    	public boolean checkInstructions() {//判断指令是否输入成功
    		if(instructions.length==0)
    		{
    			System.out.println("指令输入失败");
    			return false;
    		}
    		if(!instructions[0].equals("list")) {//判断命令格式是否正确
    			System.out.println("指令必须以list开头");
    			return false;
    		}
    		for (int i=0;i<instructions.length;i++)
    		{
    			 if(instructions[i].equals("-date")) { //读取到-date参数
 					i = setDate(++i);
 					if(i == -1) { //说明上述步骤中发现命令行出错
 						System.out.println("日期输入格式错误");
 						return false;
 					}
    			}
    			 else if(instructions[i].equals("-log")) {//读取-log输入路径
 					i = setInPut(++i);
 					if(i == -1) { //说明上述步骤中发现命令行出错
 						System.out.println("输入参数错误");
 						return false;
 					}
    			 }
    			 else if(instructions[i].equals("-out")) {//读取-out输出路径
 					i = setOutPut(++i);
 					if(i==-1) {
 						System.out.println("输出参数错误");
 						return false;
 					}
    			 }
    			 else if(instructions[i].equals("-type")) {//读取-type指令
    				 i = setType(i++);
    				 if(i==-1) {
    					 System.out.println("type指令格式错误");
    					 return false;
    				 }
    			 }
    			 else if(instructions[i].equals("-province")) {//读取-province 指令
    				 i =setNeedProvince(i++);
    				 if (i==-1) {
    					 System.out.println("province指令格式错误");
    					 return false;
    				 }
    			 }
    		}
    		return true;
    	}
    
处理举例1:
setNeedProvince()
	首先默认needprovince[]全为零是全输出,当检测到有-province时将所有置为1即都不输出,然后进行匹配。同时judge来判断是否有匹配,如果没有一个可以匹配就返回指令错误。
	    	/*需要的省份数据*/
	    	public int setNeedProvince(int i) {
	    		int judge=0;//判断有无更改
	    		for(int j = 0;j<35;j++) {//将所有定义为不输出
	    			needprovince[j] = 1;
	    		}
	    		if(i < instructions.length) {
	    			for(int j = 0;i < 35;j++) {
	    				if (province[j].equals(instructions[i])) {
	    					needprovince[j] = 0;
	    					judge=1;
	    					i++;
	    				}
	    			}
	    			if(judge == 0) {
	    				return -1;
	    			}
	    		}
	    		else {
	    			return -1;
	    		}
	    		return i;
	    	}

处理举例2:
	同上本身所有的type[]都为0都输出,检测到-type全置为1不输出,进行匹配将匹配到的重新置为0,如果没有匹配就返回错误。
    	/*指令输出数据类型*/
    	public int setType(int i) {
    		for(int j = 0;j<4;j++)//将所有类型定义为不输出
    		{
    			type[j] = 1;
    		}
    		if(i < instructions.length) {
    			if(instructions.equals("ip"))
    			{
    				type[0] = 0;
    				i++;
    			}
    			if(instructions.equals("sp")) {
    				type[1] =0;
    				i++;
    			}
    			if(instructions.equals("cure")) {
    				type[2] = 0;
    				i++;
    			}
    			if(instructions.equals("dead")) {
    				type[3] = 0;
    				i++;
    			}
    			if (type[0] == 1&&type[1] == 1&&type[2] == 1&&type[3] == 1) {
    				return -1;
    			}
    		}
    		else
    			return -1;
    		return i;
    	}

处理举例3:
	正则表达式判断路径是否合理,如果不合理返回错误。
		public int setOutPut(int i) {
			if(i < instructions.length) {
				if(instructions[i].matches("^[A-z]:\\\\(\\S+)+(\\.txt)$")) //判断字符串是不是txt文件路径
					output = instructions[i];
				else
					return -1;
			} else
				return -1;
			return i;
		}
    }
	
文件读取:
	对读到的每行进行正则表达式匹配,选择处理方式。
	    public void readTxt(String filePath){
	        try {
	        	int casenumber;
	            BufferedReader bfr = new BufferedReader(new InputStreamReader(
	            		new FileInputStream(new File(filePath)), "UTF-8"));
	            String lineTxt = null;
	            while ((lineTxt = bfr.readLine()) != null) { 
	            	if(!lineTxt.startsWith("//"))
	            	{
	            		handleCase(lineTxt);
	            	}
	            }
	            bfr.close();
	            writeTxt();
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }
		
匹配函数:
	匹配后进行相应处理。
	    /*文本处理*/
	    public void handleCase(String string) {
	    	String case1 = "(\\S+) 新增 感染患者 (\\d+)人";
	    	String case2 = "(\\S+) 新增 疑似患者 (\\d+)人";
	    	String case3 = "(\\S+) 治愈 (\\d+)人";
	    	String case4 = "(\\S+) 死亡 (\\d+)人";
	    	String case5 = "(\\S+) 感染患者 流入 (\\S+) (\\d+)人";
	    	String case6 = "(\\S+) 疑似患者 流入 (\\S+) (\\d+)人";
	    	String case7 = "(\\S+) 疑似患者 确诊感染 (\\d+)人";
	    	String case8 = "(\\S+) 排除 疑似患者 (\\d+)人";
	    	boolean isCase1 = Pattern.matches(case1, string);
	    	boolean isCase2 = Pattern.matches(case2, string);
	    	boolean isCase3 = Pattern.matches(case3, string);
	    	boolean isCase4 = Pattern.matches(case4, string);
	    	boolean isCase5 = Pattern.matches(case5, string);
	    	boolean isCase6 = Pattern.matches(case6, string);
	    	boolean isCase7 = Pattern.matches(case7, string);
	    	boolean isCase8 = Pattern.matches(case8, string);
	    	if(isCase1==true) {
	    		addIP(string);
	    	}
	    	else if(isCase2==true) {
	    		addSP(string);
	    	}
	    	else if(isCase3==true) {
	    		addCure(string);
	    	}
	    	else if(isCase4==true) {
	    		addDeath(string);
	    	}
	    	else if(isCase5==true) {
	    		moveIP(string);
	    	}
	    	else if(isCase6==true) {
	    		moveSP(string);
	    	}
	    	else if(isCase7==true) {
	    		diagnoseSP(string);
	    	}
	    	else if(isCase8=true) {
	    		ignoreSP(string);
	    	}
	    }
		
处理举例(原理都一样举一例)
	检测情况后对人前的数字进行读取。在对data二维数组进行修改
	    /*治愈患者处理*/
	    public void addCure(String string) {
	    	String[] str_arr = string.split(" "); 
	    	int i;
	    	int n = Integer.valueOf(str_arr[2].replace("人", ""));
	    	for(i = 0; i < province.length; i++) { 
	    		if(str_arr[0].equals(province[i])) {
	    			data[0][2] += n; //全国治愈人数增加
	    			data[0][0] -= n; //全国感染患者人数减少
	    			data[i][2] += n; //该省份治愈人数增加
	    			data[i][0] -= n; //该省份感染患者人数减少
	    			break;
	    		}
	    	}
	    }
		
文件写入
province[i]+typename[k]+data[i][k]进行写入。再写入前进行needprovince[i]和typr[k]进行判断是否需要写出。
	    public void writeTxt() {
	    	FileWriter fwriter = null;
	    	int i, j, k;
	        try {
	        	fwriter = new FileWriter(output);
	        	for(i = 0; i < province.length; i++) { 
	        			if(needprovince[i] == 0) {
	        				fwriter.write(province[i] + " ");
	        					for(k = 0; k < type.length; k++) {
	        							if(type[k]==0)
	        								fwriter.write(typename[k] + data[i][k] + "人 ");
	        					}
	        					fwriter.write("\n");
	        			}
	        	}
	        } catch (Exception e) {
	            e.printStackTrace();
	        } finally {
	            try {
	                fwriter.flush();
	                fwriter.close();
	            } catch (IOException ex) {
	                ex.printStackTrace();
	            }
	        }
	    }

单元检测

GitHub GitHub 2. GitHub GitHub 3. GitHub GitHub 4. GitHub GitHub 5. GitHub GitHub 6. GitHub GitHub 7. GitHub GitHub 8. GitHub GitHub 9. GitHub GitHub 10. GitHub GitHub

单元测试覆盖率优化和性能测试

git仓库链接、代码规范链接

新路历程和收获

	这个作业真的是受益匪浅,全是现学现卖,本人一直是一只菜鸡,几乎没有开发过什么课外程序,只是单纯了完成老师的作业。以前写java程序要么是多线程,要么是jdbc,第一次对字符串进行处理。同时学会了设计指令,以前都是简单的switch()或者直接用图形界面。
	刚开始看到作业的时候完全是蒙蔽的,指令系统没有一点思路,问了同学才知道了设计方法。同时因为对字符串处理完全没有经验,刚开始都想用数据库,把文本里的数据读到数据库里再输出,后来又一想用几个静态变量储存就好,然后实际写的过程中发现用静态变量还麻烦,不如直接把处理过程写成子类,这样可以直接用指令类里的数据。
	等程序写了60%以后就轻松了,有了大体的思路,有很大一部分都代码都是重复之前的工作。
	我就是老师说的d类程序员,给病人做手术时做一个,出去玩一下,回来接着做,导致我效率很低,没办法在预定时间完成任务。以后要改掉这个毛病。导致没有优化和覆盖率测试。
	本来计划昨天写完的,结果在配置javaee的tomcat我怎么配置他都和eclipse联动不起来,chrome里面可以访问localhost,eclipse就404,换了四五个tomcat版本和java版本,浪费了一晚上加一天的时间都没装好,今天写完这个作业格式化一下c盘试试。

技术路线

  • java拼车程序
    这个是个重邮的一个学长写的毕设,本科毕业直接去阿里,年薪30w大佬啊,同时因为这是他学生时期写的,也很适合我借鉴学习。
  • 会议管理系统
    这个是一个程序员给java入门用的项目,会议管理系统,供刚入行的小伙伴学习,使用的技术比较基础。
  • 博客系统
    这个是基于ssm写的博客系统,也是一个毕业年薪20w的学长写的给刚入门的小伙伴练手。
  • 一份涵盖大部分Java程序员所需要掌握的核心知识
    这个是fork最多的java学习项目
  • 完整的电商系统
    这个看上去很难是个网上商城,这学期也选了javaee这门课,这不就联动起来了。
posted @ 2020-02-21 19:58  温温温温温  阅读(200)  评论(2编辑  收藏  举报