软工1816 · 作业(二)
Github项目地址
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 10 | 20 |
• Estimate | • 估计这个任务需要多少时间 | 10 | 20 |
Development | 开发 | 380 | 495 |
• Analysis | • 需求分析 (包括学习新技术) | 60 | 70 |
• Design Spec | • 生成设计文档 | 30 | 10 |
• Design Review | • 设计复审 | 10 | 5 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 20 | 15 |
• Design | • 具体设计 | 10 | 5 |
• Coding | • 具体编码 | 120 | 270 |
• Code Review | • 代码复审 | 10 | 60 |
• Test | • 测试(自我测试,修改代码,提交修改) | 120 | 60 |
Reporting | 报告 | 50 | 75 |
• Test Repor | • 测试报告 | 30 | 10 |
• Size Measurement | • 计算工作量 | 10 | 5 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 10 | 60 |
合计 | 440 | 590 |
解题思路
首先,拿到题目的时候,先分析了一下需求:
第一步、实现基本功能
- 以命令行参数传入
- 统计文件的字符数
- 统计文件的单词总数
- 统计文件的有效行数
- 统计文件中各单词的出现次数,最终只输出频率最高的10个
- 按照字典序输出到文件result.txt
第二步、接口封装
把基本功能里的:
- 统计字符数
- 统计单词数
- 统计最多的10个单词及其词频
这三个功能独立出来,成为一个独立的模块,可以在几个地方使用:
- 命令行测试程序使用
- 在单元测试框架下使用
- 与数据可视化部分结合使用
根据题目要求,很容易想到要使用C++文件的读入读写操作来完成此次任务。所以先复习了一下文件的操作,还有上网查了一下词频的统计方法。
设计实现
根据基本功能,划分以下六个函数:
isChinese
判断是否是汉字isWord
判断是否是单词isSign
判断是否是分隔符CountChar
统计字符个数CountLine
统计有效行数CountWord
统计单词个数CountTime
统计单词频率
其中统计字符个数和有效行数都是直接读入文件,读一个字符或一个换行符计数变量就加一。比较需要花功夫的是统计单词的个数和单词频率,首先预处理txt里的内容,把所有分隔符替换成空格,并且大写全部转换为小写。之后将string
转换为stringstream
,stringstream
是以空格为界,先读入每两个空格之间的字符串再做汉字和单词的判断。至于单词的排序,采用了map
和vector
数据结构相结合,先用map
保存单词和单词频率的关系,再用vector
进行词频和字典序的排序。
代码说明
while (getline(infile, s))
{
for (int i = 0; i < s.size(); i++)
{
if (isChinese(s[i], s[i + 1]) == 1)//是汉字则跳过
{
i++;
}
else
{
if (isSign(s[i]) == 1)//是分隔符
{
s[i] = ' '; //将分隔符都换成空格
}
}
}
str.append(s);
str.append(1, ' ');
}
transform(str.begin(), str.end(), str.begin(), ::tolower); //将大写转化为小写
stringstream ss(str); //分割成一个个字符串
map<string, int> strMap; //保存的结果
string strTmp; //分割后的字符串
while (ss >> strTmp)
{
if (isWord(strTmp) == 1) //判断是否为单词
{
map<string, int>::iterator it = strMap.find(strTmp);
if (it == strMap.end())
{
strMap.insert(map<string, int>::value_type(strTmp, 1)); //插入map
}
else
strMap[strTmp]++; //词频+1
}
}
vector<pair<int, string> > vec;
MapSortOfValue(vec, strMap); //利用vec排序
for (vector<pair<int, string> >::iterator it = vec.begin(); it != vec.end(); it++)
{
n++;
if (n <= 10) //选出词频最高的10个单词
{
vec2.push_back(make_pair(it->first, it->second));
}
}
sort(vec.begin(), vec.end(), cmp); //最后再以字典序排序
心路历程
首先很抱歉,由于这一周刚好新生入学,而我作为班导自然义不容辞需要带领他们,新生教育周的活动安排得非常密集,所以我除了上课之外的空闲时间都在带新生。每天基本上都是十一点才能回到宿舍有自己的时间,第二天早上六七点又要起床。很难有时间静下心来写程序。就连作业发表后我也是直到第二天才有时间看一眼。这次作业我没有完成得很好,实现了基本功能后就已经没剩什么时间再完成扩展功能了,还有性能分析和单元测试,这是我之前没有接触过的,再学习新技能明显已经来不及了。单元测试的Bug还没改完,最后在性能分析的时候,VS崩溃了,连运行都运行不了,导致只能先把已做完的部分提交。
所以,建议给自己的deadline可以比任务的实际deadline早那么一天,好应对一些突发状况。
再接再厉吧。下一次作业一定不这么赶了。