个人作业——词频统计

时间:2022-01-03 21:57:15

                                                                个人作业
                                                         ——词频统计


一、项目概况

对源文件(*.txt,*.cpp,*.h,*.cs,*.html,*.js,*.java,*.py,*.php等,文件夹内的所有文件)统计字符数、单词数、行数、词频,统计结果以指定格式输出到默认文件中,以及其他扩展功能,并能够快速处理多个文件。

 

二、需求分析

(1)基本功能

a) 统计文件的字符数;

b) 统计文件的单词总数;

c) 统计文件的总行数;

d) 统计文件中各单词的出现次数,输出频率最高的10个;

e) 对给定文件夹及其递归子文件夹下的所有文件进行统计;

f) 统计两个单词(词组)在一起的频率,输出频率最高的前10个;

g) 在Linux系统下,进行性能分析,过程写到blog中(附加题)。

(2)输入与输出要求

a) 输入以命令行参数传入(文件夹的路径);

b) 在当前路径输出最终结果文件result.txt。

 

三、功能模块与设计

(1)遍历文件夹

a)使用 _finddata_t 结构体,及 _findfirst 和 _findnext等 函数来查找文件并遍历子文件夹;

b)采用深度优先搜索,判断是文件夹则遍历该文件夹,是文件则进行计数。

(2)统计文件中的字符、单词数、行数

a)用fgetc()读取字符,ASCII码值≥32且<=126则计数加一;

b)行数目前是每个文件换行符数目+1;

c)单词数先用字符数组记录两个分隔符之间的所有字符(字母/数字),再判断是否符合单词定义,符合则计数加一。

PS:很糟心的是目前这三项和样例的结果都对不上...都或多或少差了几百....实在不知道哪里错了...于是我打算先来写博客了....

(3)统计各单词、词组出现频率

a)用两个哈希表来进行查找计数,哈希函数采用ELFhash函数,采用开散列法(拉链法);

b)单词结构体包括次数、单词(同类则保存ASCII码最小的那个)、除去单词最末尾的数字剩下部分的小写(便于判断是否属于同一单词);

c)词组结构体包括次数、两个单词的指针;

(4)对单词、词组出现频率进行排序,各找出前十个并输出

a)目前采用的是最简单的一个方法,用一个容量为10的数组,对全部单词、词组一次遍历,依次数组内容比较,最后数组保留的即为最大的10个。

 

四、代码实现

(1)遍历文件夹

a)main函数先判断是文件还是文件夹

个人作业——词频统计个人作业——词频统计
 1 _finddata_t fileInfo;
 2 long Handle = _findfirst(argv[1], &fileInfo);
 3 
 4 if (Handle != -1L && (fileInfo.attrib & _A_SUBDIR) == 0)
 5 {
 6     //It's a file name and not a folder path 
 7     CountQuantity(argv[1]);
 8 }
 9 else
10 {    
11     //it's a folder path
12     TraverseFolder(argv[1]);
13 }
View Code

 b)递归遍历文件夹

函数原型:void TraverseFolder(string folderPath) ;

 

(2)字符数、行数、单词数计数

函数原型:void CountQuantity(const char* fileName);//传入文件名

 

(3)单词频率统计

单词结构体:

函数原型:int ELFhash(char* key);//哈希函数

                  wordList CountFrequency(char word[], int lengthPre);//传入单词字符及除去位于最后的数字的单词长度,返回单词结点(便于词组使用)

                  void Mystrncpy_lwr(char* &s, char *t, int k);//自定义的一个从字符串t拷贝指定长度字符串到字符串s,并转化为小写字母的函数

     

(4)词组频率统计

词组结构体:

函数原型:int ELFhash_Phrase(char* key1, char* key2);//用于词组的哈希函数,使词组中两个单词对函数返回值都有用处

                  void CountFrequency_Phrase(wordList word1, wordList word2);//传入词组中两个单词的指针

 

(5)找出单词、词组中的前10个

函数原型:void Top10WordPhrase();

 

五、代码质量和性能分析

(1)质量分析

(2)性能分析

 

 个人作业——词频统计

 

 分析:

 

六、测试设计与分析

(1)助教的样例

运行时间:16s左右(release模式)

输出结果:字符数、行数、单词数均有偏差(╯﹏╰)b;

     前十单词结果正确;

                  前十词组结果正确;

                  个人作业——词频统计个人作业——词频统计

 

                                         (左为我的输出,右为样例输出)

(2)

 

七、总结收获

 

附:

(1)Github管理代码

个人作业——词频统计

(2)PSP表格

Status

Stages

预估耗时/min

实际耗时/min

Accept

【计划】 Planning

60

 80

Accept

——估计时间 Estimate

60

 80

Accept

【开发】 Development

790

 

Accept

——需求分析 Analysis

10

 5

Accept

——设计文档 Design Spec

40

40

Accept

——设计复审 Design Review

10

10

Accept

——代码规范 Coding Standard

10

 5

Accept

——具体设计 Design

60

100

Accept

——具体编码 Coding

480

750

Accept

——代码复审 Code Review

60

40

Accept

——测试 Test

120

 

Accept

【记录用时】 Record Time Spent

20

 

Accept

【测试报告】 Test Report

60

 

Accept

【算工作量】 Size Measurement

20

 

Accept

【总结改进】 Postmortem

40

 

Accept

【合计】 Summary

990