一、 实验内容:
1. 对源文件(*.txt,*.cpp,*.h,*.cs,*.html,*.js,*.java,*.py,*.php等,文件夹内的所有文件)统计字符数、单词数、行数、词频,统计结果以指定格式输出到默认文件中,以及其他扩展功能,并能够快速地处理多个文件。
2. 使用性能测试工具进行分析,找到性能的瓶颈并改进
3. 对代码进行质量分析,消除所有警告
4. 设计10个测试样例用于测试,确保程序正常运行(例如:空文件,只包含一个词的文件,只有一行的文件,典型文件等等)
5. 使用Github进行代码管理
6. 撰写博客
二、 需求分析:
按功能模块分析:
- 遍历目录下所有文件。
- 文本模式读写文件。
- 统计文件总字符数。
- 统计文件总行数。
- 统计文件总单词数。
- 统计文件中出现所有单词及其个数。
- 统计文件中出现所有词组及其个数。
- 找出单词、词组中出现频率最高的十个元素。
- 按字典序输出(统计单词时不区分大小写)。
- 移植Linux。
三、 设计方案:
按功能模块设计:
- 1. 文件夹遍历
使用WIN32_FIND_DATA、FILETIME结构体,递归遍历目录下所有文件。
详情请见:http://www.cnblogs.com/collectionne/p/6792301.html
- 2. 文本模式读写文件
读取FILE,fopen,fgetc,fclose;输出:ofstream,outfile。
- 3. 字符数
fgetc读入字符,根据作业要求按aclii码判断符合char_number++。
- 4. 行数
fgetc读入字符,若为换行符,line_number++;对于结尾没有换行符直接EOF的加一。
- 5. 单词数
fgetc读入字符,buf用于存储字符串,j用于统计字符串长度,flag用于记录当前是否有字符串在存贮,m用于记录字符串中前连续字母的长度——通过对j长度的buf截取前m个实现真正单词的存储与计数。
- 6. 单词频数
通过unordered_map存储单词大写形式与出现频数,即unordered_map<string, double> dic;实现快速查找,修改频数。
- 7. 词组频数
int p判断buff中是否有单词存储,若无,读到单词直接存入buff并加入空格,若有,单词后插入buff,得到词组存储,再将该单词直接存入buff并加入空格。通过unordered_map存储词组大写形式与出现频数,即unordered_map<string, double> phr;实现快速查找,修改频数。
- 8. 排序
初始化一个含有两个元素string和int的结构体,分配10个空间,遍历map,对元素按num进行插入排序。
- 9. 字典输出
通过unordered_map<string, string> diction存储单词大写形式与检测到与该单词不区分大小写相同的字典排序最优形式。通过排序得到的string在unordered_map<string, string> diction中搜索,得到字典排序最优形式,输出。
10. Linux移植
文件遍历使用Get_All_Files()将所有路径存入vector中,遍历路径即可。
四、 测试样例:
- 空目录、空文件、只包含空文件的文件夹
正常输出各项均为0的result。对非目录文件提示输入目录文件结束进程。
- 对空文件、不含换行符的文件、结尾无换行符的文件
正确输出行数。
- newsample
多次测试,result稳定,字符数500的误差,百万分之二点八;总行数100的误差,十万分之四点三;单词数9500的误差,万分之五点七。Top ten 单词与词组完全正确。
五、 性能分析:
对项目进行性能分析:
占据大部分时间的是unordered_map的内部hash,无法优化。
getcharnum是核心函数,字符行数单词词组的判断都在其中,逻辑已多次优化。
trans是将字符串转换为大写的函数,考虑到字符中小写较多,故尝试修改将字符串转换为小写的函数
通过trans与其他函数相对工作比较,稍有成效。
六、 PSP表格
任务内容 |
计划时间 |
实际用时 |
计划 |
20 |
5 |
估算各任务所需时间规划工作步骤 |
20 |
5 |
开发 |
1280 |
1060 |
需求分析 |
10 |
20 |
模块解决 |
10 |
10 |
技术算法调研 |
60 |
30 |
具体写代码 |
800 |
700 |
测试 |
200 |
150 |
优化 |
200 |
150 |
报告 |
150 |
180 |
总结报告 |
120 |
150 |
经验总结 |
30 |
30 |
总计 |
1450 |
1245 |
七、 经验总结
本次作业我受益良多
工程方面:
- 完成了PSP。
- 使用GitHub进行了项目版本管理。
- 设计用例完成了单元测试。
- 撰写了博客完成了项目总结。
- VS性能探查器做了性能分析。
技术方面:
- 学习了win下遍历文件目录。
- 学习了unordered,map的使用。
- 加深了对string的理解、文件流读入写出以及C++类的理解。
- 学习了new和malloc对与结构体的区别。
- 学习了Linux移植和gdb调试代码。
整体来说,对这次作业完成情况还算满意。一开始技术调研一定要做好,代码框架数据结构定好避免大改。多查GitHub、论坛,避免造轮子;与同学间多交流,避免闭门造车;合理规划时间,调整作息,避免通宵。