第一次个人编程作业

第一次个人编程作业

Part 1 : Github项目地址

由于我的vs一直没办法直接把项目上传到github上,一直推送失败。所以我只能在github的对应仓库上“create new file",直接把代码贴上去,望谅解。通过设置新的分支后已经可以成功推送!耶!


Part 2 : PSP(Personal Software Process)表格

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

Part 3 : 解题思路描述

(1)拿到题目后如何思考?

在看到助教姐姐发布的第一次编程作业后,我的内心是崩溃的。由于在给出的三种语言要求中,java没接触过,python选修课学过但学得很浅,所以我就选择了用c++来解题。后来发现用c++简直太难了啊啊啊啊!停止土拨鼠尖叫,回到题目,题目要求将小王打乱的地址簿规范化处理。对我来说,难点在于:一是地址中的“省”、“市”等关键字有可能残缺,这就说明没办法简单的通过匹配该关键字来提取。只能通过暴力打表或者引入地图API来匹配处理;二是没处理过文件的输入输出,需要进一步了解这里面有没有什么陷阱(坑)以及如何规范输入输出;三是好多处理问题上的细节,类处理函数处理之类的。总之就是一个字,。但生活还是得继续下去,冲!

(2)如何查找资料?

主要有四种方式:翻阅以前的c++教材和c++ primary,熟悉一下可能会用到的语法;利用搜索引擎查找地址模糊匹配等与题目相关类似的博客资料;询问身边的大佬们,向他们请教思路;围观软工群里“神仙打架”,我还没想好怎么做他们已经写好评测工具等着了QUQ。


Part 4 : 设计实现过程

(1)代码组织方式

我定义了一个person类,里面包含成员变量total,name,telnum,province,city,county,street,detailaddr,函数则有stringtowstring转换函数、wstringtostring转换函数、省提取函数、市提取函数以及以下几级地址的提取函数,通过提取函数将提取出来的规范地址赋值给类中对应的成员变量,转换函数则用来实现string和wstring的相互转换。

全局变量与函数如下图:

Person类成员变量如下图:

以下是关系函数的流程图:

(2)算法的关键

总的来说:

我的算法的关键主要是地址的提取函数和字符转换函数。因为不会调用地图API(别问,问就是菜!),所以只能采用暴力的本方法来查找匹配。我建立了地址数组,将普通地址和特殊地址分开,比如直辖市和自治区单独建组,不与普通省份一起,方便匹配并且提取规范地址,赋值比较方便,通过返回已提取地址的字数来简化地址,以便下一步匹配提取。但这种方法非常暴力,效率比较低,还需要进一步的完善改进。;通过stringtowstring和wstringtostring的转换函数来实现字符的转换,方便对字符串的处理和输出。

地址提取函数:

一是省、直辖市、自治区的地址提取函数。因为这种情况下的参数相对较少,因此我就建立了三个全局变量字符数组来存省、直辖市、自治区的地址名称,然后通过函数进行对比匹配。由于存在直辖市和自治区这两种比较复杂的情况,因此我将其分开进行判断,先进行直辖市的判断:

        //判断直辖市
	for (int i = 0; i < 4; i++) {
		if (t == direct_pro[i]) {
			addr[p].province = t; addr[p].city = t; addr[p].city += L"市";
			if (obj_[2] == L'市') { return 3; }
			else return 2;
			break;
		}
	}

自治区的判断:

	//判断自治区
	if (z == autop[2]) { addr[p].province = L"西藏自治区"; return 5; }

	if (z == autop[0]) { addr[p].province = L"内蒙古自治区"; return 6; }

	if (z == autop[1]) { addr[p].province = L"宁夏回族自治区"; return 7; }

	else if (z == autop[3]) { addr[p].province = L"广西壮族自治区"; return 7; }

	if (z == autop[4]) { addr[p].province = L"新疆维吾尔自治区"; return 8; }

普通省份的判断,注意需要把黑龙江省单独提出来判断:

	//判断普通省份
			for (int j = 0; j < 22; j++) {
				if (t == provincebook[j]) {
					t += L"省";
					if (obj_[2] == L'省') { addr[p].province = t; return 3; break; }
					else { addr[p].province = t; return 2; break; }
				}
			}

二是对市、区/县/县级市、街道/镇/乡、详细地址的提取。到这里我就GG了。不会调地图api,而如果采用上述方法,需要存的参数太过于庞大,因此只能先不考虑“市”、“县”等关键字缺失的情况和部分关键字与地名重合的情况,直接通过匹配关键字来提取。显然这是一个漏洞很多的本方法,还需要想出办法来改进。

	//识别“市”关键字
	for (int i = 0; i < 5; i++) {
		city_ += obj[i];
		if (obj[i] == L'市') {
			addr[c].city = city_;
			return i + 1; break;
		}
            }

字符串转换函数:

从文件直接getline得到的字符串对汉字的处理比较奇怪,一个汉字需要占字符数组的两个单位,这给字符匹配和处理增加了很多麻烦。然后我就去百度惹(百度是镇滴好用!我爱csdn!)~发现通过把string转换成wstring后,再进行各种处理,会方便很多。因此就增加了两个转换函数。
以下是把string转换成wstring的函数:

wstring result;
	//获取缓冲区大小,并申请空间,缓冲区大小按字符计算  
	int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
	TCHAR* buffer = new TCHAR[len + 1];
	//多字节编码转换成宽字节编码  
	MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
	buffer[len] = '';             //添加字符串结尾  
	//删除缓冲区并返回值  
	result.append(buffer);
	delete[] buffer;
	return result;
}


Part 5 : 计算模块接口部分的性能改进。

(1)记录在改进计算模块性能上所花费的时间,描述你改进的思路。

要改进计算模块性能,我觉得最重要的还是能学会调用地图API来进行匹配处理(或者还有另一种更简单的方法?),简化编程和节约时间空间。然鹅这个我还不会啊啊啊,给我时间,我觉得我阔以!

(2)展示一张性能分析图(由VS 2017/JProfiler的性能分析工具自动生成),并展示你程序中消耗最大的函数。

或许性能分析图是下面这个嘛?问了度娘就只查到了这个,应该是的吧……

CPU使用情况百分比

热路径和执行单个工作最多的函数

调用树(可见程序中消耗最大的函数)


Part 6 : 计算模块部分单元测试展示。

暂时还没有做单元测试这一项。待完成后再来补。


Part 7 : 计算模块部分异常处理说明。在博客中详细介绍每种异常的设计目标。每种异常都要选择一个单元测试样例发布在博客中,并指明错误对应的场景。

由于代码本身存在的bug问题,除了较为正常的未缺关键字的地址,异常情况的发生率还挺高的。特别是因为关键字引起的异常,比如:

1、关键字缺少。

“张三,福建福州闽13599622362侯县上街镇福州大学10#111.”这种情况下提取结果为{“姓名”:“张三”,“手机”:“13599622362”,“地址”:[“福建省”,“”,“福州闽侯县”,“上街镇”,“福州大学10#111.”]},使得市的提取失败,福州被匹配到县,间接导致县的提取失败。

2、关键字与地名重复。

“小美,北京市东15822153326城区交道口东大街1号北京市东城区人民法院.”这种情况下提取结果为{“姓名”:“小美”,“手机”:“15822153326”,“地址”:[“北京”,“北京市”,“东城区”,“交道”,“口东大街1号北京市东城区人民法院.”]},将详细地址错误匹配到上级地址中。


Part 8 : 个人心得体会

总归一个字,“菜”!两个字“好菜”!三个字,“我好菜”!哎,果然编程能力都是要靠时间日积月累,临时抱佛脚真的会很难受。不过这次编程,大概是我大学以来,除了打比赛以外,做得最认真的编程作业了。而且也大部分都是自己”薅光头发“写出来的,虽然功能还很垃圾,用了很多笨方法,但就有一种自己尽力了而且收获得蛮多的“快感”。也许这就是我当初选择计算机专业想追求的那种满足感吧。未来熬夜秃头打代码的日子还长着,需要进步学习的还非常非常多,要坚持!冲!

原文地址:https://www.cnblogs.com/cyj0107/p/11532946.html