第一次个人编程作业

一、仓库地址

二、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 45 60
· Estimate · 估计这个任务需要多少时间 45 60
Development 开发 1850 2205
· Analysis · 需求分析 (包括学习新技术) 270 360
· Design Spec · 生成设计文档 60 90
· Design Review · 设计复审 30 45
· Coding Standard · 代码规范 (为目前的开发制定或选择合适的规范) 20 30
· Design · 具体设计 300 330
· Coding · 具体编码 780 840
· Code Review · 代码复审 90 150
· Test · 测试(自我测试,修改代码,提交修改) 300 360
Reporting 报告 110 125
· Test Report · 测试报告 60 60
· Size Measurement · 计算工作量 30 35
· Postmortem & Process Improvement Plan · 事后总结, 并提出改进计划 20 30
  · 合计 2005 2390

三、计算模块接口的设计与实现过程

(1)解题思路

思考和找资料过程:

  刚打开作业的时候,天花乱坠的要求直接把我整懵了,头晕,再打开,还是头晕。逃避了一会,想着早点看懂题目能够早点开始,决定看个大概之后,从代码着手:
  1.题目中的数据是姓名、手机号和地址这三个字符串和一些标点符号的组合,而题目要求我们将其分开,同时去掉一些标点,我想着是否有一些方法能够去把这些字符串分开,向大佬寻求帮助后得知可以使用Java的正则表达式,于是去慕课和一些博客中学习了相关知识。
  2.之后想着如果通过正则表达式能够将姓名、手机号和地址分开的话,应该也能够再利用它来对地址进行详细的划分,果不其然,正则表达式真是个好东西(激动地搓搓手。
  3.接着就是仔细分析代码需求了,在这上面真是走了不少弯路。大致了解了三个level的要求,首先level1是要求对地址进行五级划分,而level2和level3则是七级划分,level1和level2都会出现“省”和“市”这两个字符会缺失的情况,而level3和它们根本不是一个level,它会出现缺失,甚至需要补全,了解到需要导入地图,ok fine,我先放弃这个,能把level1和level2打出来,再尝试一下去解决补全的问题,对于不同级别的不同情况,我打开了淘宝,选择设置收货地址,随手点一点找了一下不同的情况。
  再之后考虑的就是github和其他要求里面需要下载的软件的使用了,也是跟着几篇博客里面的教程一步一步做下来。同时感觉很幸运有认识的好友是学计算机的,我从他们那里获得了不少帮助,也很感谢班上认真解答我的疑问的同学。

解题步骤

Step 1. 利用正则表达式将前缀x!,姓名,手机号和地址分开
Step 2. 通过分离出来的前缀x判断进行什么级别的地址划分
Step 3. 利用正则表达式判断是否为直辖市并且分割剩余的详细地址

(2)设计实现过程

  我利用Java来写这个程序。由于都是字符串切割这一类问题,我只用了一个类。类中有一个main方法和其他几种工具方法和输出方法,在main方法中先对字符串进行切割,把前缀x,姓名,手机号和地址分开后,先调用getProvince方法判断是否有省级或者市级的级别后缀缺失,再根据前缀x的不同,调用了不同的方法进行地址的详细划分,最后通过输出函数输出。以下是几个方法:

方法

方法名 说明
Map<String, Object> getJson(ArrayList arrayList,String name,String phone) 输出函数
ArrayList getMatchesAddress (String address) 工具函数:用于进行Level1的详细地址划分
ArrayList getMatchesAddressSeven (String address) 工具函数:用于进行Level2和Level3的详细地址划分
ArrayList getProvince(String address) 工具函数:用于解决缺少省、市等字符串的情况

算法关键及独到之处

算法关键
1、将前缀x!,姓名,手机号和地址的分开处理,同时删除最后的英文句号“.”。
step1.通过“,”将字符串切割成x!+姓名和手机号+地址两部分

   				String level_name = str.split(",")[0];
   				String level = level_name.split("[!]")[0];

step2.通过“!”分割前缀x和姓名

				String name = level_name.split("[!]")[1];
				String phone_address = str.split(",")[1];

step3.通过创建匹配器的方式分割手机号和地址

				Pattern pattern = Pattern.compile("((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}");
				//创建匹配给定输入与此模式的匹配器。
				Matcher matcher = pattern.matcher(phone_address);
				while(matcher.find()) {
				sb2.append(matcher.group());				}
				String phone = sb2.toString();
				String address = phone_address.replaceAll(phone, "");

step4.用replaceAll删除“.”

				address = address.replaceAll("[.]","");

2、用getProvince方法处理省级或者市级的级别后缀缺失的情况。
我的方法很简单,总而言之就是用了if---else语句:
判断判断是否有“省” :if(!address.matches(".*省.*")){}
有则进入之后的利用前缀x判断进行什么级别的地址划分,
没有则接着判断是否有“市”:if(address.matches(".*市.*")) {}
没有则接着判断第三级地址else if(address.matches(".*(区|县).*")){}
将缺失的级别后缀补全,结束后返回xx省xx市+后面的详细地址。

3、根据前缀x判断进行五级地址分割还是七级地址分割,通过getMatchesAddress方法进行五级地址分割,通过getMatchesAddressSeven进行七级地址分割。
  五级和七级的分割道理其实是差不多的,就是利用正则表达式逐级分割,我的方法还是很简单,简单来说就是把每一级的不同情况列举出来,所以碰到比较不规则的地址的时候可能会出错。我就拿七级地址分割来说,找出每一级地址的不同情况,比较不一样的是省级,还需要判断是否是直辖市。

  • 省级:
			if(address.matches(".*(省|自治区|行政区).*")) {
			int index = address.indexOf("省");	
			int index2 = address.indexOf("自治区");	
			int index3 = address.indexOf("行政区");	
			if(index > -1) {
				pr = address.substring(0,index+1);
				temp = temp.substring(index+1);
			}
			if(index2 > -1) {
				pr = address.substring(0,index2+3);
				temp = temp.substring(index2+3);
			}
			if(index3 > -1) 
			{
				pr = address.substring(0,index3+3);
				temp = temp.substring(index3+3);
			}
			if(pr.matches(".*北京.*")) {
				pr = "北京";
				temp = address.substring(index+1);
			}
			
			if(pr.matches(".*上海.*")) {
				pr = "上海";
				temp = address.substring(index+1);
			}
			
			if(pr.matches(".*天津.*")) {
				pr = "天津";
				temp = address.substring(index+1);
			}
			if(pr.matches(".*重庆.*")) {
				pr = "重庆";
				temp = address.substring(index+1);
			}				
		}
  • 市级:
		if(temp.matches(".*市.*")) {
			int index = temp.indexOf("市");
			if(temp.matches(".*北京.*|.*上海.*|.*天津.*|.*重庆.*"))
			{
				city = temp.substring(0,index+1);
			}
			else{
				city = temp.substring(0,index+1).replace(pr,"").trim();
			}
			temp = temp.substring(index+1);
		}

剩余的五个级别同理:

  • 第三级:if(temp.matches(".*(区|县|市|海域|岛|旗).*")) {}
  • 第四级:if(temp.matches(".*(街道|镇|乡).*")) {}
  • 第五级:if(temp.matches(".*(路|巷|道|街|弄|胡同).*")) {}
  • 第六级:if(temp.matches(".*号.*")) {}
  • 第七级:else {village = temp;}

4、最后用getJson方法输出。

独到之处
  嗯,我的方法真的很简单,毕竟只是个速成品,把地址单独分割出来后,利用正则表达式分割详细地址,在每一级中不停地判断和列举,并没有什么特别的地方。但是能解决一定问题的方法就是好方法嘛,对于我来说能有输出已经是一件很快乐的事情了。非要厚脸皮地说有什么独到之处的话,简单粗暴算嘛,勉强算吧,嘻嘻。(给点面子

四、计算模块接口部分的性能改进

(1)改进时间

  这个真的花了蛮多时间的,至少三个小时,甚至更多,首先是因为没有看清楚代码需求,不知道要分级,也不知道不同级别对应不同的情况,还有就是没有考虑到不同级别的不同情况,一开始只考虑省市区县这样简单的几种情况,后来发现还有其他比较少见的一些情况,比如自治区、特别行政区之类的。

(2)改进思路

  • 分级:把前缀分割出来后,利用前缀进行划分,同时设置两种方法,分别用于五级地址分割和七级地址分割。
  • 不同级别的不同情况:在我能想到和找到的情况范围内,在每个级别进行判断和列举。

(3)性能分析图

我使用的是Jprofiler进行性能分析

消耗最大的方法是getMatchesAddress:

public static ArrayList<String> getMatchesAddress (String address) {
		String	pr = "";
		String	city = "";
		String	county = "";
		String	town = "";
		String	village = "";
		String temp = address;
		if(address.matches(".*(省|自治区|行政区).*")) {
			int index = address.indexOf("省");	
			int index2 = address.indexOf("自治区");	
			int index3 = address.indexOf("行政区");	
			if(index > -1) {
				pr = address.substring(0,index+1);
				temp = temp.substring(index+1);
			}
			if(index2 > -1) {
				pr = address.substring(0,index2+3);
				temp = temp.substring(index2+3);
			}
			if(index3 > -1) 
			{
				pr = address.substring(0,index3+3);
				temp = temp.substring(index3+3);
			}
			if(pr.matches(".*北京.*")) {
				pr = "北京";
				temp = address.substring(index+1);
			}
			
			if(pr.matches(".*上海.*")) {
				pr = "上海";
				temp = address.substring(index+1);
			}		
			if(pr.matches(".*天津.*")) {
				pr = "天津";
				temp = address.substring(index+1);
			}	
			if(pr.matches(".*重庆.*")) {
				pr = "重庆";
				temp = address.substring(index+1);
			}	
		}
		if(temp.matches(".*市.*")) {
			int index = temp.indexOf("市");
			if(temp.matches(".*北京.*|.*上海.*|.*天津.*|.*重庆.*"))
			{
				city = temp.substring(0,index+1);
			}
			else{
				city = temp.substring(0,index+1).replace(pr,"").trim();
			}
			temp = temp.substring(index+1);
		}
		if(temp.matches(".*(区|县|市|海域|岛|旗).*")) {
			int index = temp.indexOf("区");
			int index2 = temp.indexOf("县");
			int index3 = temp.indexOf("市");
			int index4 = temp.indexOf("海域");
			int index5 = temp.indexOf("岛");
			int index6 = temp.indexOf("旗");
			if(index > -1) {
				county = temp.substring(0,index+1).replace(city, "").trim();
				temp = temp.substring(index+1);
			}
			if(index2 > -1) {
				county = temp.substring(0,index2+1).replace(city, "").trim();
				temp = temp.substring(index2+1);
			}
			if(index3 > -1) {
				county = temp.substring(0,index3+1).replace(city, "").trim();
				temp = temp.substring(index3+1);
			}
			if(index4 > -1) {
				county = temp.substring(0,index4+2).replace(city, "").trim();
				temp = temp.substring(index4+2);
			}
			if(index5 > -1) {
				county = temp.substring(0,index5+1).replace(city, "").trim();
				temp = temp.substring(index5+1);
			}
			if(index6 > -1) {
				county = temp.substring(0,index6+1).replace(city, "").trim();
				temp = temp.substring(index6+1);
			}
		}
		if(temp.matches(".*(街道|镇|乡).*")) {
			int index = temp.indexOf("街道");
			int index2 = temp.indexOf("镇");
			int index3 = temp.indexOf("乡");
			if(index > -1) {
				town = temp.substring(0,index+1).replace(county, "").trim();
				village = temp.substring(index+1);
			}
			if(index2 > -1) {
				town = temp.substring(0,index2+1).replace(county, "").trim();;
				village = temp.substring(index2+1);
			}
			if(index3 > -1) {
				town = temp.substring(0,index3+1).replace(county, "").trim();
				village = temp.substring(index3+1);
			}
		}else {
			village = temp;
		}
		ArrayList<String> arrayList = new ArrayList<String>();
		arrayList.add(pr);
		arrayList.add(city);
		arrayList.add(county);
		arrayList.add(town);
		arrayList.add(village);
		return arrayList;
	}

五、计算模块部分单元测试展示

(1)单元测试代码

public class test2 {
	public static void main(String[] args) {
		String[] arr = {"山西省太原市小店区鼓西街道湖滨路119号湖滨大厦一层",
						"广西壮族自治区南宁市江南区白沙大道20号",
						"新疆维吾尔自治区乌鲁木齐市乌鲁木齐县万盛大街4706号",
						"湖南省长沙市天心区芙蓉中路二段116-1众东国际104室",
						"福建省厦门市集美区理工南路852号厦门工艺美术学院4#205",
						"四川省成都市武侯区人民南路四段20号叶婆婆钵钵鸡",
						"福建省泉州市丰泽区丰泽街道丰迎路15号",
						"福建省泉州市鲤城区庄府巷107号",
						"湖南省长沙市天心区裕南街85号盟重烧烤",
						"云南省水富县云川路1号水富火车站货运大楼",
		for (int a = 0; a < arr.length; a++) {
			Object[] array = getProvince(arr[a]).toArray();
			for (int i = 0; i < array.length; i++) {
				System.out.println(array[i]);}
			System.out.println("---------------------------------------------");}}
		public static ArrayList<String> getMatchesAddressSeven (String address) {
		String	pr = "";
		String	city = "";
		String	county = "";
		String	town = "";
		String	path = "";
		String	mark = "";
		String	village = "";
		String temp = address;
		if(address.matches(".*(省|自治区|行政区).*")) {
			int index = address.indexOf("省");	
			int index2 = address.indexOf("自治区");	
			int index3 = address.indexOf("行政区");	
			if(index > -1) {
				pr = address.substring(0,index+1);
				temp = temp.substring(index+1);
			}
			if(index2 > -1) {
				pr = address.substring(0,index2+3);
				temp = temp.substring(index2+3);
			}
			if(index3 > -1) 
			{
				pr = address.substring(0,index3+3);
				temp = temp.substring(index3+3);
			}
			if(pr.matches(".*北京.*")) {
				pr = "北京";
				temp = address.substring(index+1);
			}
			
			if(pr.matches(".*上海.*")) {
				pr = "上海";
				temp = address.substring(index+1);
			}
			
			if(pr.matches(".*天津.*")) {
				pr = "天津";
				temp = address.substring(index+1);
			}
			if(pr.matches(".*重庆.*")) {
				pr = "重庆";
				temp = address.substring(index+1);
			}						
		}
		if(temp.matches(".*市.*")) {
			int index = temp.indexOf("市");
			if(temp.matches(".*北京.*|.*上海.*|.*天津.*|.*重庆.*"))
			{
				city = temp.substring(0,index+1);
			}
			else{
				city = temp.substring(0,index+1).replace(pr,"").trim();
			}
			temp = temp.substring(index+1);
		}
		if(temp.matches(".*(区|县|市|海域|岛|旗).*")) {
			int index = temp.indexOf("区");
			int index2 = temp.indexOf("县");
			int index3 = temp.indexOf("市");
			int index4 = temp.indexOf("海域");
			int index5 = temp.indexOf("岛");
			int index6 = temp.indexOf("旗岛");
			if(index > -1) {
				county = temp.substring(0,index+1).replace(city, "").trim();
				temp = temp.substring(index+1);
			}
			if(index2 > -1) {
				county = temp.substring(0,index2+1).replace(city, "").trim();
				temp = temp.substring(index2+1);
			}
			if(index3 > -1) {
				county = temp.substring(0,index3+1).replace(city, "").trim();
				temp = temp.substring(index3+1);
			}
			if(index4 > -1) {
				county = temp.substring(0,index4+2).replace(city, "").trim();
				temp = temp.substring(index4+2);
			}
			if(index5 > -1) {
				county = temp.substring(0,index5+1).replace(city, "").trim();
				temp = temp.substring(index5+1);
			}
			if(index6 > -1) {
				county = temp.substring(0,index6+1).replace(city, "").trim();
				temp = temp.substring(index6+1);
			}
		}
		if(temp.matches(".*(街道|镇|乡).*")) {
			int index = temp.indexOf("街道");
			int index2 = temp.indexOf("镇");
			int index3 = temp.indexOf("乡");
			if(index > -1) {
				town = temp.substring(0,index+2).replace(county, "").trim();
				temp = temp.substring(index+2);
			}
			if(index2 > -1) {
				town = temp.substring(0,index2+1).replace(county, "").trim();;
				temp = temp.substring(index2+1);
			}
			if(index3 > -1) {
				town = temp.substring(0,index3+1).replace(county, "").trim();
				temp = temp.substring(index3+1);
			}
		}
		if(temp.matches(".*(路|巷|道|街|弄|胡同).*")) {
			int index = temp.indexOf("路");
			int index2 = temp.indexOf("巷");
			int index3 = temp.indexOf("道");
			int index4 = temp.indexOf("街");
			int index5 = temp.indexOf("弄");
			int index6 = temp.indexOf("胡同");
			if(index > -1) {
			path = temp.substring(0,index+1).replace(town, "").trim();
			temp = temp.substring(index+1);}
			if(index2 > -1) {
				path = temp.substring(0,index2+1).replace(town, "").trim();
				temp = temp.substring(index2+1);}
			if(index3 > -1) {
				path = temp.substring(0,index3+1).replace(town, "").trim();
				temp = temp.substring(index3+1);}
			if(index4 > -1) {
				path = temp.substring(0,index4+1).replace(town, "").trim();
				temp = temp.substring(index4+1);}
			if(index5 > -1) {
				path = temp.substring(0,index5+1).replace(town, "").trim();
				temp = temp.substring(index5+1);}
			if(index6 > -1) {
				path = temp.substring(0,index6+2).replace(town, "").trim();
				temp = temp.substring(index6+2);}
		}
		
		if(temp.matches(".*号.*")) {
			int index = temp.indexOf("号");
			mark = temp.substring(0,index+1).replace(path, "").trim();
			village = temp.substring(index+1);
		}
		else {
			village = temp;
		}
		ArrayList<String> arrayList = new ArrayList<String>();
		arrayList.add(pr);
		arrayList.add(city);
		arrayList.add(county);
		arrayList.add(town);
		arrayList.add(path);
		arrayList.add(mark);
		arrayList.add(village);
		return arrayList;
	}

测试答案为:

山西省
太原市
小店区
鼓西街道
湖滨路
119号
湖滨大厦一层

---------------------------------------------
广西壮族自治区
南宁市
江南区

白沙大道
20号


---------------------------------------------
新疆维吾尔自治区
乌鲁木齐市
乌鲁木齐县

万盛大街
4706号


---------------------------------------------
湖南省
长沙市
天心区

芙蓉中路

二段116-1众东国际104室

---------------------------------------------
福建省
厦门市
集美区

理工南路
852号
厦门工艺美术学院4#205

---------------------------------------------
四川省
成都市
武侯区

人民南路
四段20号
叶婆婆钵钵鸡

---------------------------------------------
福建省
泉州市
丰泽区
丰泽街道
丰迎路
15号


---------------------------------------------
福建省
泉州市
鲤城区

庄府巷
107号


---------------------------------------------
湖南省
长沙市
天心区

裕南街
85号
盟重烧烤

---------------------------------------------
云南省

水富县

云川路
1号
水富火车站货运大楼

---------------------------------------------

(2)测试的函数

测试的函数是getMatchesAddressSeven,已经在(1)中展示

(3)构造测试数据的思路

构造测试数据来源主要有三种:
1、选择了一些比较奇怪的名字,比如自治区、巷、街之类的。
2、从百度地图上随手点了一个位置。
3、选择了一些我去过的地方。

(4)测试覆盖率图

主方法的覆盖率:

测试方法的覆盖率:

六、计算模块部分异常处理说明

(1)在输入的省级是xxx自治区xx市,且省级和市级后缀都缺失的情况下,会出现补全错误和信息缺失的现象。
输入:2!小王,广西壮族15822153326南宁江南区白沙大道20号.
输出:{"姓名":"小王","手机":"15822153326","地址":["广西省","族市","宁江南区","","白沙大道","20号",""]}
(2)针对上面那种情况我想试试看如果把市级后缀加上是否会出现缺失,虽然不出现缺失了,但是把省市混淆在一起了。
输入:2!小王,广西壮族15822153326南宁市江南区白沙大道20号.
输出:{"姓名":"小王","手机":"15822153326","地址":["广西壮族南宁省","广西壮族南宁市","江南区","","白沙大道","20号",""]}
(3)还有一些奇怪的地址也会出现异常,比如字符串中出现连续的两个“市”,输出会出现缺失。
输入:1!佘减觉,山东省枣庄市市中区13878001733大郭庄村216号大郭庄幼儿园.
输出:{"姓名":"佘减觉","手机":"13878001733","地址":["山东省","枣庄市","大","","郭庄村216号大郭庄幼儿园"]}

七、在PSP表格记录实际花费的时间

八、小结

  说实话,从无到有的过程真是太坎坷了,现在凌晨三点,我啃了一个月饼续命。对于我来说主要的困难在主要于:
  (1)对于需求分析不够透彻,走了很多弯路,带来了很多不必要的麻烦。
  (2)学习一门新的语言Java。
  (3)熟悉并掌握一些完全陌生的软件,比如eclpise,jProfiler,并且利用它们去进行程序的测试、分析。
  (4)Github的上传,这太难了,难中难,困扰了我好久,我到现在都不知道我的程序能不能测评。
  每天熬到两三点,我只觉得涂到脸上的精华都给这几天熬夜熬没了。但是苦尽甘来,收获还是蛮多的:
  (1)大致了解了如何去规划完成一个程序的时间和步骤,以后
  (2)做一件事情之前一定要看清需求,分析清楚怎么做以后,再着手去做。
  (3)Java算是入了个门,也浅浅地掌握了正则表达式。
  (4)对于eclipse和jProfiler也有了一定程度的熟悉度。
  (5)大概了解了如何进行单元测试和性能分析。
  有种开学胜期末的感觉, 累但是它值得。

原文地址:https://www.cnblogs.com/cathyccathy/p/11521360.html