第一次个人编程作业
1.github
地址:https://github.com/ruifeng-1/031702533
2.PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
20 |
30 |
· Estimate |
· 估计这个任务需要多少时间 |
10 |
10 |
Development |
开发 |
600 |
660 |
· Analysis |
· 需求分析 (包括学习新技术) |
200 |
120 |
· Design Spec |
· 生成设计文档 |
20 |
30 |
· Design Review |
· 设计复审 |
120 |
150 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 |
30 |
· Design |
· 具体设计 |
30 |
20 |
· Coding |
· 具体编码 |
200 |
300 |
· Code Review |
· 代码复审 |
120 |
30 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
300 |
500 |
Reporting |
报告 |
30 |
20 |
· Test Repor |
· 测试报告 |
30 |
20 |
· Size Measurement |
· 计算工作量 |
10 |
10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
10 |
10 |
|
· 合计 |
1720 |
1940 |
3.计算模块接口的设计与实现过程
需求
题目:损坏的地址簿
描述如下:
公司给实习生小王安排了一个任务,要求将一份客户地址规范化处理,地址簿原先是这样的:
王先生,13756899511,福建福州闽侯上街镇福州大学.陈先生,15063321552,福建省福州市鼓楼区鼓西街道湖滨路233号.
这样的地址不够规范,公司要求小王将地址规范化为如下的字典格式,并存储为json文件:
[{"姓名":"王先生","手机":"13756899511","地址":["福建省","福州市","闽侯县","上街镇","福州大学"]},
{"姓名":"陈先生","手机":"15063321552","地址":["福建省","福州市","鼓楼区","鼓西街道","湖滨路233号"]}]
可是小王不仅没完成任务,还把原始文件弄乱了,手机号码被混杂在地址数据中,请帮小王恢复文件并完成他的任务。
文件现状:
李四,福建省福州13756899511市鼓楼区鼓西街道湖滨路110号湖滨大厦一层.
张三,福建福州闽13599622362侯县上街镇福州大学10#111.
王五,福建省福州市鼓楼18960221533区五一北路123号福州鼓楼医院.
小美,北京市东15822153326城区交道口东大街1号北京市东城区人民法院.
小陈,广东省东莞市凤岗13965231525镇凤平路13号.
请把文件格式化为如下形式:
[{"姓名"':"李四","手机":"13756899511","地址":["福建省","福州市","鼓楼区","鼓西街道", "湖滨路110号湖滨大厦一层"]},
{"姓名":"张三","手机":"13599622362","地址":["福建省","福州市","闽侯县","上街镇", "福州大学10#111"]},
{"姓名":"王五","手机":"18960221533","地址":["福建省","福州市","鼓楼区","","五一北路123号福州鼓楼医院"]},
{"姓名":"小美","手机":"15822153326","地址":["北京","北京市","东城区","","交道口东大街1号北京市东城区人民法院"]},
{"姓名":"小陈","手机":"13965231525","地址":["广东省","东莞市","","凤岗镇","凤平路13号"]}]
请注意:
1.直辖市与一般城市的匹配区别,如样例中的小美。
2.手机号码一定不会和地址中的数字相邻,即不会出现福州市西二环路11380502116922号或者福州大学30#31395521336233这样的情况。
3.地址最终格式应为["直辖市/省","直辖市/市","区/县/县级市","街道/镇/乡","详细地址"]
4.该难度题目不会出现违背题目规则的异常样例。
当你把该任务做好之后,产品经理突发奇想,让你进一步匹配详细地址,进而区分出详细地址中的街道、道路名、门牌号等信息,文件则因变成:
[{"姓名":"李四","手机":"13756899511","地址":["福建省","福州市","鼓楼区","鼓西街道","湖滨路","110号","湖滨大厦一层"]},
{"姓名":"张三","手机":"13599622362","地址":["福建省","福州市","闽侯县","上街镇","","","福州大学10#111"]},
{"姓名":"王五","手机":"18960221533","地址":["福建省","福州市","鼓楼区","","五一北路","123号","福州鼓楼医院"]},
{"姓名":"小美","手机":"15822153326","地址":["北京","北京市","东城区","","交道口东大街","1号","北京市东城区人民法院"]},
{"姓名":"小陈","手机":"13965231525","地址":["广东省","东莞市","","凤岗镇","凤平路","13号",""]}]
请注意:该难度题目中,并非所有的路都叫XX路,也可能叫XX街,XX巷,需自行搜集数据。
产品经理还有个大胆的想法,但是已经被大部分程序员打爆了,没人愿意做,如果你觉得你做得来,可以试一试。地址簿中存在 福建福州市公园路15号 这样的地址,希望能利用地图数据自动补全缺省信息,将其格式化为["福建省","福州市","仓山区","公园路","15号"]或者更完善的形式。(附加题)
设计思路
1.我使用的是VC++(附带第三方库boost库,因为要使用正则表达式)因为个人能力有限,因此仅针对难度1!和2!。
2.题目的需求是从字符串中分离出难度,姓名,手机号码,地址,再将地址分为五级\七级地址,因此我学习了正则表达式来匹配字符串里的特定字符串,另外因为字符串有中文字符,只能用宽字符串即wstring进行匹配。
3.首先匹配出难度,姓名,手机号码,我封装了三个函数来分别实现这三个功能,正则表达式分别为:(L"[1-3]!"),(L"\\w+?[^\\,]"),(L"[0-9]{11}")。(前置L代表宽字符串)
4.地址方面,利用各个关键字“省”“市”“县”等匹配出各级地址,直辖市则用特殊情况处理,然后可依据前面的难度输出五级\七级地址。
类和函数
分为两个类Text(文本类)和Address(地址类),具体函数如下:
class Text//文本类 { public: Text() {} wstring select_level(wstring s);//选择难度 wstring find_name(wstring s);//寻找姓名 wstring find_number(wstring s);//寻找手机号码 void show();//输出 wstring Level();//返回难度 private: wstring name;//姓名 wstring number;//手机号码 wstring address;//地址 wstring level;//难度 };
class Address//地址类 { public: Address() {} void find_address(wstring s);//寻找地址 wstring search_address(wstring wstr, wregex wre);//正则搜索 bool match_address(wstring wstr, wregex wre);//正则匹配 void show(wstring level);//输出,调用了Text类上的level private: wstring province;//省 wstring city;//市 wstring county;//县 wstring town;//镇 wstring road;//路 wstring house_number;//门牌号 wstring detail;//详细地址 };
关键及独到之处
关键就是使用了正则表达式匹配特定字符串(我学了两三天才弄懂怎么在c++用上正则),以及每处匹配完之后,我会用cstring库中的substr函数删除字符串中匹配过的无效信息(跟噶韭菜似的)。
4.计算模块接口部分的性能改进
性能改进
由于Address类中要调用大量的正则表达式进行匹配各级地址,因此我对find_address()函数进行了优化,把原本在find_address()函数中匹配字符串的内容提取出来,单独写了search_address()和match_address()函数,从而在find_address()函数中进行调用,前者返回匹配结果,后者返回是否匹配成功。
性能分析图
5.计算模块部分单元测试展示
6.计算模块部分异常处理说明
1.由关键字作为正则表达式匹配,后来发现地址中省市两级的后缀可能会省略,于是只能改用暴力搜索,在匹配省的正则表达式里放入了全国所有省份的信息,市级地址由于实在太多,所以暂时无法解决省略市级后缀的字符串。
2.发现测试手机号码在末尾的字符串时会出现异常,原因是我在匹配手机号码后对字符串的处理是简单合并两边的字符串,导致手机号码在末尾时出现异常,因此可以改变此时的判定,只需要留下左边的字符串即可。
3.门牌号匹配时出现异常,原因是门牌号并不全是数字字符串。
7.总结
第一次作业,连续熬夜了几天,从正则表达式开始学起,中间经过了数次阵痛(各种代码写不通,软件不会用),也没写出什么值得一看的代码,包括直到现在也是非常不完善的版本,但是收获也是有的,比如学会了正则表达式(其中因为c++的特性,安装boost库也让我苦恼了整整一天)等等,希望接下来能继续努力,最好学一下java和python,用c++实在太难了。