一,需要满足的需求
1.统计文件的字符数
2.统计文件的单词书
3.统计文件的行数
4.统计文件中各单词的出现次数
5.对给定文件夹及其递归文件夹下的所有文件进行统计
6.统计两个单词(词组)在一起的频率,输出频率最高的前10个。
二,功能设计:
1.统计 ASCII码 32 到126的字符
2.根据单词定义判断两个分隔符直接是否为一个单词
3.用' '来计算行数
4.遍历文件夹
5.用命令行参数输入
6.使用unordered_map存储
6.遍历unordered_map,选出前十个单词
8.统计词组数
三.具体设计
- 利用自己编写的chuli函数来将一个字符串分解为有效部分和后缀,同时将有效部分大小写归一。
- 使用unordered_map进行统计
- 寻找词频前十的单词时,维护一个10个大小的“榜单”,线性遍历哈希表,用其中的每一个元素来更新“榜单”,时间复杂度O(N)
四,过程分析
1.遍历文件夹
使用vector 作为容器,结构体files[i]的成员file[i].c_str(),就是一个文件的绝对地址,用fopen_s打开
void Tongji(char* fp1) { vector<string> files; char * filePath = fp1; //获取该路径下的所有jpg文件 //getFiles(filePath, "jpg", files); //获取该路径下的所有文件 getFiles(filePath, "*", files); //列表文件输出路径 // FILE* fp; FILE* fp2; //fopen_s(&fp, "d:\Adobe\dir_list.txt", "w"); int size = files.size(); for (int i = 0; i < size; i++) { fopen_s(&fp2, files[i].c_str(), "r"); countword(fp2); fclose(fp2); } //fclose(fp); }
void getFiles(string path, string exd, vector<string>& files) { //cout << "getFiles()" << path<< endl; //文件句柄 long hFile = 0; //文件信息 struct _finddata_t fileinfo; string pathName, exdName; if (0 != strcmp(exd.c_str(), "")) { exdName = "\*." + exd; } else { exdName = "\*"; } if ((hFile = _findfirst(pathName.assign(path).append(exdName).c_str(), &fileinfo)) != -1) { do { //cout << fileinfo.name << endl; //如果是文件夹中仍有文件夹,迭代之 //如果不是,加入列表 if ((fileinfo.attrib & _A_SUBDIR)) { if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) getFiles(pathName.assign(path).append("\").append(fileinfo.name), exd, files); } else { if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) files.push_back(pathName.assign(path).append("\").append(fileinfo.name)); } } while (_findnext(hFile, &fileinfo) == 0); _findclose(hFile); } }
2.countword
函数的功能是,读取一个文件的每个字符的同时,统计字符数,单词数,行数,利用chuli函数处理有效的单词,将其封装成一个结构体,送入uordered_map中。
1 int countword(FILE* stream) 2 { 3 4 char ch; 5 char word_stream[1024] = { '