windows下遍历目录统计字符、单词、词组

该博客介绍了如何在Windows环境下遍历目录,统计文本文件的字符数、单词数、行数以及词频。文章详细阐述了实现过程,包括使用C++的unordered_map存储单词和词组频率,以及如何处理文件遍历和统计中的各种细节问题。通过遍历文件夹、读取文件、哈希表操作和输出结果等步骤,实现了高效的数据统计。
摘要由CSDN通过智能技术生成

需求分析

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

  具体要求:

  1. 统计文件的字符数(只需要统计Ascii码,汉字不用考虑)

  2. 统计文件的单词总数

  3. 统计文件的总行数(任何字符构成的行,都需要统计)

  4. 统计文件中各单词的出现次数,输出频率最高的10个。

  5. 对给定文件夹及其递归子文件夹下的所有文件进行统计

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

  ps:

a) 空格,水平制表符,换行符,均算字符

  b) 单词的定义:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。

  英文字母:A-Z,a-z

  字母数字符号:A-Z,a-z,0-9

  分割符:空格,非字母数字符号

 

时间安排

 

  PSP表:

流程

预估时间/h

实际时间/h

需求分析

0.5

0.5

具体设计

1.5

1

具体编码

6

8

代码测试

2

2

性能优化

2

1

总结报告

2

2.5


实现过程

1、首先确定遍历文件方式,为减少模块间的耦合度,先提取出总目录下所有非目录文件的文件名,用 string[] fileName 来存储,方便之后的文件操作。c标准库里提供了一结构体  _finddata_t  来记录文件信息,其中就包含了该文件是否为目录文件,若是,则递归调用遍历函数访问子文件夹;若否,则用  _findnext()  函数找下一文件。将访问过的文件的文件名与其目录结合成路径保存在  fileName  中。

 

复制代码
void SearchFiles(char* dir,string fileName[],int& fileNum)
{
    intptr_t handle;
    _finddata_t findData;
    char searchdir[200],newdir[200],newfile[200];

    strcpy_s(searchdir, dir);
    strcat_s(searchdir, "\\*");
    handle = _findfirst(searchdir, &findData); 

    if (handle == -1)
    {
        cout << "Failed to find first file!\n";
        return;
    }

    do
    {
        if (strcmp(findData.name, ".") != 0 && strcmp(findData.name, "..") != 0)
        {
            if (findData.attrib == _A_SUBDIR)
            {
                strcpy_s(newdir, dir);
                strcat_s(newdir, "\\");
                strcat_s(newdir, findData.name);
                SearchFiles(newdir,fileName,fileNum);
            }    
            else
            {
                strcpy_s(newfile, dir);
                strcat_s(newfile, "\\");
                strcat_s(newfile, findData.name);
                fileName[fileNum]=newfile;
                fileNum+=1;                
            }
        }
    } while (_findnext(handle, &findData) == 0);    

    _findclose(handle);   
}
复制代码

 

2、单词与其出现个数的关系用哈希表来存储,这里采用 C++ STL 函数  unordered_map() <string,int> wordValueMap ,由于按照要求 file 与 FilE231为同一单词,则再建立一张哈希表  unordered_map() <string,int> wordValueMap ,其中 wordValueMap  的  string  存储一个单词最简单的名字,即脱去所有后缀数字且字母全部转化为小写,而  wordNameMap  则将单词的最简名字映射到实际出现的且按照要求应该保留的名字。这种方式将查找名字与选取合适的名字分开,可以更方便地进行哈希表查找。

 

3、对  fileName  中每个文件进行读操作,使用  fgetc()  进行逐个字符阅读,并存储在  string word  中,若遇到非字母数字字符,则判断  word  是否以四个字母打头,若是则  word 是一个单词,将其写入  wordValueMap  (无则添加,已存在则个数加1),并判断是否要在  wordNameMap  中更改它的实际名字。在此过程中同时记录字符数、单词数、行数(出现“\n”则加1,且每个文件最末尾加1)。为了能够统计词组情况,设置了一全局数组  string allWords[] ,将读文件过程中所有的单词(最简单形式)读入  allWords 。

  

复制代码
void ReadFile(FILE *fp, unordered_map<string, int>& wordValueMap, unordered_map<string, string>& wordNameMap, int& chrtCount, int& wordCount, int& lineCount)
{
    char ch;
    string word;
    unsigned int i,j;
    unordered_map<string, int>::iterator itValue;
    unordered_map<string, string>::iterator itName;

    while ((ch = fgetc(fp)) != EOF)
    {
        if (ch >= 32 && ch <= 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值