词频统计
1.项目要求和基本功能
项目要求
- 对源文件(*.txt,*.cpp,*.h,*.cs,*.html,*.js,*.java,*.py,*.php等,文件夹内的所有文件)统计字符数、单词数、行数、词频,统计结果以指定格式输出到默认文件中,以及其他扩展功能,并能够快速地处理多个文件。
- 使用性能测试工具进行分析,找到性能的瓶颈并改进
- 对代码进行质量分析,消除所有警告,http://msdn.microsoft.com/en-us/library/dd264897.aspx
- 设计10个测试样例用于测试,确保程序正常运行(例如:空文件,只包含一个词的文件,只有一行的文件,典型文件等等)
- 使用Github进行代码管理
- 撰写博客
基本功能
- 统计文件的字符数(只需要统计Ascii码,汉字不用考虑)
- 统计文件的单词总数
- 统计文件的总行数(任何字符构成的行,都需要统计)
- 统计文件中各单词的出现次数,输出频率最高的10个。
- 对给定文件夹及其递归子文件夹下的所有文件进行统计
- 统计两个单词(词组)在一起的频率,输出频率最高的前10个。
- 在Linux系统下,进行性能分析,过程写到blog中(附加题)
2.PSP表格
Statu | Stages | 预估耗时/min | 实际耗时/min |
Accept | 【计划】 | 30 | 20 |
Accept | 估计时间 | 30 | 20 |
Accept | 【开发】 | 1330 | 1910 |
Accept | 需求分析 | 20 | 30 |
Accept | 设计文档 | 30 | 30 |
Accept | 设计复审 | 10 | 5 |
Accept | 代码规范 | 10 | 5 |
Accept | 具体设计 | 60 | 60 |
Accept | 具体编码 | 600 | 1000 |
Accept | 代码复审 | 300 | 300 |
Accept | 测试 | 300 | 480 |
Accept | 【记录用时】 | 10 | 10 |
Accept | 【测试报告】 | 30 | 60 |
Accept | 【算工作量】 | 10 | 10 |
Accept | 【总结改进】 | 60 | 60 |
Accept | 【合计】 | 1470 | 2090 |
3.解题思路
数据结构:
全局变量
unsigned long characterNum;//存放字符数 unsigned long wordNum; //存放单词数 unsigned long lineNum; //存放行数
采用结构体数组(动态内存)存储单词及其出现次数
struct wordInfo { char* wordStr; char** nextWordPoint; int* nextWordFrequency; int presentNextWordNum; int frequency; int strlength; int wordLength;//不包含最后的数字部分 }; struct alphaArray { wordInfo* wordArray; int presentWordArrayLength; }; struct wordStatisticsResult { char* wordStr; int wordFrequency; }; struct phaseStatisticsResult { char* firstStr; char* secondStr; int phaseFrequency; };
遍历文件的方法:
_findfirst,_findnext函数实现(Windows平台),参考例程
readdir函数实现(Linux平台),参考例程
具体实现方案:
1>主函数:
初始化各变量
遍历给定文件夹中的每个文件
只读方式打开符合要求的文件
单词统计,词组统计
循环至所有文件遍历完成
关闭文件
输出统计结果
2>单词统计:
遍历字符并统计
判断是否是换行符并统计
建立缓冲区域存储一个单词中连续的字符
采集单词字符串
生成单词的哈希值(散列函数使用ELFHash、冲突解决方案采用二次探测)
根据首字母和哈希值确定单词的存储位置并存储单词信息
将当前单词的地址存储到前一个单词的结构体中,以实现词组频率统计
3>词组统计:
存储单词
返回当前单词在词表中的位置
如果不是第一个单词
根据位置得到字符串指针
在前一个单词的结构体中查找是否存在该指针
如果存在 该指针对应计数加一
如果不存在 存储该指针,初始化数量为1
记录该位置
最后遍历即可得到所有词组出现频率
4.代码实现
(1)初始化词表
1 void dictionaryInit(struct alphaArray* dictionary) 2 { 3 int i, j, k; 4 characterNum = 0; 5 wordNum = 0; 6 lineNum = 0; 7 for (i = 0; i < alphabet; i++) 8 { 9 (dictionary + i)->wordArray = (wordInfo*)malloc(sizeof(wordInfo)*wordArrayLength); 10 (dictionary + i)->presentWordArrayLength = wordArrayLength; 11 if ((dictionary + i)->wordArray == NULL) exit(-1); 12 for (j = 0; j < (dictionary + i)->presentWordArrayLength; j++) 13 { 14 ((dictionary + i)->wordArray + j)->wordStr = (char*)malloc(sizeof(char)*wordStrLength); 15 if (((dictionary + i)->wordArray + j)->wordStr == NULL) exit(-1); 16 *(((dictionary + i)->wordArray + j)->wordStr) = '