github仓库地址:
https://github.com/fzugame/071708131.git
PSP表格:
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
10 |
10 |
· Estimate |
· 估计这个任务需要多少时间 |
10 |
20 |
Development |
开发 |
20 |
30 |
· Analysis |
· 需求分析 (包括学习新技术) |
320 |
640 |
· Design Spec |
· 生成设计文档 |
20 |
20 |
· Design Review |
· 设计复审 |
60 |
30 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
10 |
10 |
· Design |
· 具体设计 |
60 |
50 |
· Coding |
· 具体编码 |
560 |
660 |
· Code Review |
· 代码复审 |
30 |
40 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
90 |
120 |
Reporting |
报告 |
60 |
60 |
· Test Repor |
· 测试报告 |
20 | 20 |
· Size Measurement |
· 计算工作量 |
10 |
10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
10 |
10 |
|
· 合计 |
1290 |
1730 |
程序接口实现:
通过从网上下载的全国各省市区名称手动处理文件便于计算机读取,并且将文档转码为Utf-8编码(统一编码规则)。设置一个类来建立省市索引(省的名称分别在第几行,省的下面几行就是这个省的下设市)。设置一个类来存储五级地址结构,通过类的继承方式再创建一个类来存储七级地址。接下来按行读取输入文件得到得到姓名和手机号。处理地址时,提取逗号后面的两个字作为与省市区名称文件比对,比对成功赋值完整省份名称(四个直辖市直接赋值到市级单位),接下来市名类似。区级地址根据关键字“区,县”等关键字匹配,镇级,村级,门牌号按类似处理方法。3级难度不全缺失部分,在程序中未实现,因为需要调用地图API,这方面还未学习。
处理过程如下图所示:
关键函数及功能
Person1::getaddress_simple | 处理五级地址的函数 |
Person2::getaddress_left | 处理剩余的三级地址 |
Indexes::Indexes | 建立索引,便于比对 |
print_to_file | 转码输出文件 |
change_to_w | UTF-8转UNICODE |
计算模块接口部分性能改进:
这张图是性能改进后的截图,可以看到print_to_file这个函数做占用的时间是最多的因为print_to_file这个函数承担着将答案从Unicode编码转换到utf-8编码方式,并且打开文件按json格式输出,最后再关闭文件等功能,但是这些占用时间是正常的。在性能未改进前建立索引的时间是最长既 index类内按索引读取文件的函数,其次才是输出函数priint_to_file,最后我采用增加内存占用的方式来减少性能消耗即将全国省市区名称文件内容都存储在一个wstring数组内不仅不需要频繁的开关文件而且还加快了比对速度。改进后的函数如下:
Indexes::Indexes() { wnum = 0; int p[34] = { 0,3,17,29,47,57,69,87,91,94, 106,118,131,146,156,170,189,204,219,241, 256,259,267,289,299,316,324,335,350,359, 365,381,386,391 }; for (int i = 0; i < 34; i++) { province[i] = p[i]; } ifstream fin(FILENAME); string str; while (!fin.eof()) { //cout << "1" << endl; getline(fin, str); pc[wnum++] = change_to_w(str); } fin.close(); fin.clear(); }
计算模块单元测试:
因为cpp评测工具两次导致电脑奔溃死机,所以就没有列出详细的数据,这里我贴出我的运行程序运行结果与答案对比
可以看到答案对比基本正确说明程序的正确性。
处理地址的函数如下:
void Person1::getaddress_simple(wstring& wstr, char* argv, const Indexes& sone) { int i = 2, mark = 0; while (wstr[i] != L',')i++; int len = (int)wstr.size(); wstring result = L"\"地址\":[\""; //开始处理省级单位 i++; int flag = 0; province = L""; while (flag < 2) { if (wstr[i] != L'!') { province = province + wstr[i]; flag++; } i++; } if (province == L"北京" || province == L"重庆" || province == L"上海" || province == L"天津") { //cout << "hello" << endl; city = province + L"市"; while (wstr[i] == L'!' || wstr[i] == L'市') { i++; } } else { wstring lin = L""; int j; for (j = 0; j < pnum; j++) { lin = lin + pc[sone.province[j]][0] + pc[sone.province[j]][1]; if (province == lin) { //cout << "yes there is"<province = pc[sone.province[j]]; break; } lin = L""; } mark = j; int len = (int)province.size(); j = 2; while (j < len || wstr[i] == L'!') { if ((wstr[i] != L'!') && (wstr[i] != province[j]))break; else if ((wstr[i] != L'!') && (wstr[i] == province[j])) { j++; i++; } else i++; } //开始处理市级单位 city = L""; city = city + wstr[i]; i++; city = city + wstr[i]; flag = 0; for (j = sone.province[mark] + 1; j < sone.province[mark + 1]; j++) { lin = L""; lin = lin + pc[j][0]; lin = lin + pc[j][1]; if (lin == city) { flag = 1; len = 0; city = L""; while (pc[j][len] != L':') { city = city + pc[j][len]; len++; } break; } }
计算模块部分异常处理说明:
异常情况就是在处理电话号码时如果电话号码在门牌号后面就会得到错误的电话,而且会出现程序异常终止的清况,最后我在处理电话号码的模块中加入判断机制如果没有11位就再次寻找直到找到正确的号码 最后成功解决了此项问题。