实验要求
-
基本功能
- 统计文件的字符数
- 统计文件的单词总数
- 统计文件的总行数
- 统计文件中各单词的出现次数
- 对给定文件夹及其递归子文件夹下的所有文件进行统计
- 统计两个单词(词组)在一起的频率,输出频率最高的前10个。
- 在Linux系统下,进行性能分析,过程写到blog中(附加题)
前期准备
需求分析
本次作业要求对任意文件或者特定目录下所有文件中的字符、单词、词组做相应的统计,并将统计结果以文件的形式保存。分析需求,主要的需求和困难点如下:
1、细节要求多,整个项目的任务主体结构看起来简单,但是细节有很多值得推敲的地方,如:字母的大小写显示,单词的可能组成,具体应该选择的存储结构(吃大亏啊),要想高效的解决细节问题,必须得有良好的设计思路,形成这样的思路并不简单。
2、新手上路,最担心的就是技术、工具和思路上的匮乏,可以预见的是,做项目的过程中,将会遇到许多time-consuming的情况,解决问题的能力将成为这次项目完成效果好坏的瓶颈。
3、针对具体需要学习的工具,有单元测试工具,项目管理流程工具及思路,性能分析工具等,需要及时掌握。
4、优化代码,将会是费脑的过程。
代码规范
Visual Studio已经有对代码风格进行自动规范的功能,在此基础上我参考了刘泽的习惯(自己一开始不会写啊,很悲伤,天生就不是写文档的料),结合Menci大神的总结,暂定了以下规范:
- 所有的
#include
指令必须放置于整个程序开头。 应尽量将代码按功能进行合理的分块。
#include
中,C 标准库头文件应该放置于 C++ 标准库头文件前,其它头文件(如果有)应放置于最后。- 对于每个代码块,使用 4 空格或等长的 Tab 缩进。
-
花括号必须遵循「花括号不换行」,且左花括号的左边必须有且仅有一个空格。所有右花括号必须与上一级代码块的缩进相同。
-
多个意义独立的代码块之间应该用空行隔开。
-
右花括号前不应该有多余的空行。
-
不应该有两个连续的空行。
-
非空行尾不应该有多余的空格。
-
所有的
#include
指令之后必须有一个空行。 -
如果有
using namespace std;
,则必须紧跟在#include
后的空行后,之后必须一个空行。 -
main
函数的返回值类型必须是int
,可以省略return 0;
。 -
空函数体可以使用
{}
。 - 传参时,应该根据实际需要使用「引用」、「
const
引用」和「值传递」。 -
应该尽量少使用全局变量。
-
局部变量必须在用时定义,变量名不应该与上一个块中的变量重名,可以与全局变量重名。
- 逗号
,
与for
中的分号;
后面必须有一个空格,前面不能有空格。 -
双目运算符、三目运算符的两侧必须有一个空格。单目运算符的两侧不能有空格。冒号的两侧必须有一个空格。
条目较多,希望能够时刻遵守吧。其实感觉在写的时候一点问题没有,但是开始调试了以后就瞬间乱了,所谓越调越乱,就是这个道理吧。
PSP表格----随着进度会随时更新
最初的规划(极度不专业,经验也匮乏,很蛋疼)
- 项目大小:第一眼估计大概在1000-2000行代码左右吧
项目时间:目测给自己的要求是10小时(编程+前期学习),调试5-10小时
项目质量:待评估
是否按时交付:这个要考验我自己的速度和能力了,加油吧
事实上工作量早就超过了……回想起来感觉十分尴尬,前期学习大概就花了7-8h(走神和中间做别的事情的时间没有算,如果算的话就恐怖了),编写大概用了10h左右,所以说这个估计对于我这个新手来说怕是完全不合理的,而调试的时间更是直奔10h+,emmmm,唯一欣慰的是自己学习了很多东西吧!在这里不详细说,留待总结时一一道来。
后面参考了优秀报告的样板,做过第一次以后就有经验啦!
PSP2.1 |
任务内容 |
计划完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
30 |
30 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
30 |
30 |
Development |
开发 |
900 |
1700 |
Analysis |
需求分析 (包括学习新技术) |
180 |
480 |
Design Spec |
生成设计文档 |
30 |
30 |
Design Review |
设计复审 (和同事审核设计文档) |
10 |
10 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
20 |
10 |
Design |
具体设计 |
40 |
60 |
Coding |
具体编码 |
300 |
450 |
Code Review |
代码复审 |
60 |
150 |
est |
测试(自我测试,修改代码,提交修改) |
40 |
500 |
Reporting |
报告 |
240 |
- |
Test Report |
测试报告 |
60 |
- |
Size Measurement |
计算工作量 |
30 |
- |
Postmortem & Process Improvement Plan |
事后总结 ,并提出过程改进计划 |
150 |
- |
Summary |
合计 |
780 |
- |
设计思路
不得不吐槽一下自己:一开始想着所有的工作自己来完成(基础类,存储结构自己编写),太想让自己从底层搬砖做起,结果过度执着于搬砖,浪费了许多时间(有许多优良的库可以供我使用)。
既然点进来了就看看我一开始的思路吧:
1、一开始想错了,以为是需要对单个文件和所有文件都做统计,还在构思文件类,事后被废弃;
2、用word_count类保存单词(里面含义丰富,但肯定有冗余),具体的实现过程中由于一开始对单词做的分析不够,所以后来不断在增加功能,浪费了不少回头想,回头对程序的时间。
3、用phrase_count类保存单词,基于word_count相同的思路来完成
4、设计word_classifier类作为字符流——单词判别器,在编写这个类的过程中,我逐渐体会到了类的使用方式和编写的初步感觉,是一个令人愉快的设计!
5、最大的败笔:用基于字典序的二叉排序树来存储单词和词组,由于时间不足没有写出平衡的树,,事实证明,要这么多数据结构,光是分配空间和存储就已经足够浪费时间,而对整个项目的单词量的估计不足,更让我陷在了这个坑里。只记得书本上写的:O(logn)的查找时间,却忘记了建立树是高昂的开销,而且调试困难,错误百出,光是在这个部分所浪费的时间就足足有5、6个小时以上,代码量(现已废弃)更是占到了第一个版本的80%,工作量极大而又不讨好,事后在优化过程中我连热图分析都没做,就直接将结构改成了stl库的unordered_map,时间瞬间提升8倍(800%的优化,意味着初步的设计师(我)该被开除出个人项目)。
由于刘泽说我抄他的模板(至少是结构),我决定把图删掉,以后自己画一个(今晚实在不想画了),吹咩!你不也是抄模板的吗!反正我遇到的坑那么多,随便就画多几个图啦。
具体的项目