【tips】【词频统计】中可能用到的资源,以C++为例

  前言

  我不知道C#什么情况,不过C++里面,什么参数都不传时,argc=1,argv里面是当前程序名。当你传入dir时,argc=2,当你传入-e dir时,argc=3。

  这个文章十分适合有一点C语言基础,然后想自己独立完成这个作业的童鞋。预计只有一点点C语言基础的童鞋只需要5个小时左右就能搞定~

  如果有帮助请点赞。。还有哦。。blog里肯定不能给出代码的是吧,blog里面不能!!!~

  分析词频统计这个题目,主要需要实现3个部分:

  1. 递归的查找一个文件夹下面符合规则的文件。
  2. 对于每一个合法文件,进行读入,按照“单词规则”进行词的划分。
  3. 对于所有的词进行统计,排序,输出。

  这肯定不会给出源码。但是肯定对C语言基础的童鞋独立完成作业有很大的帮助!

  文件读入

  这里给出一个简单的方法:

  如果我们知道每个合法文件的绝对路径,就可以依次打开文件进行读取(用C的fopen或者C++的ifstream)。关键是如何知道一个文件夹下面所有的文件。如果你会使用CMD,就会知道在windows环境下dir这个指令和列出文件目录有关。通过查看dir的帮助文档,发现用如下命令可以递归的列出一个文件夹下面所有文件:

dir [dictionary] /S /B > FileDir.tmp

  并且cmd支持正则表达式,所以可以用*.txt等直接获得合法的文件。后面的大于号表示将输出保存到当前目录下面的FilrDir.txt文件中:

  于是我们就获得了所有需要统计的文件的绝对路径。这些信息保存在当前目录下的一个tmp文件中(其实就是一个文本文件)。关键是怎么在C++里面执行这个指令。stdlib.h里面有一个函数叫system(char* userCmd),表示在cmd里面执行userCmd命令。其中userCmd是一个字符串。所以我们可以在程序里面用system()函数执行那句命令,然后得到tmp文件。统计的时候,只需要把地址依次读出,然后打开那个地址指向的文件。统计词频就可以。好吧。。看来这里有很多问题。。。

  显然在你直接使用这个命令的时候不会出现任何问题。

system(argv[argc-1]);

  但在程序里面测试实际地址的时候,竟然有人写了如下语句,然后还一直埋怨说调试过不了:

char str[100]="D:\n.txt";
system(str);

  我不想用咆哮体,但。。。但忍不住啊!!!你输出回车的时候用的是什么啊?不是printf("\n");吗?难道就木有发现\是个转意字符吗?正确的写法是D:\\Dir好不好啊!!!

  

  单词划分 这个用不用C++特性无所谓,唯一需要的是细心,不要漏掉规则。

 

  词频统计

  如果说,让你统计有n个100以内的数字,每个数字出现的次数。这个很简单,你肯定会开一个长度101的数组arr,然后每当k出现一次,arr[k]++。但现在是统计单词出现次数。C++里面你可以是用一个东西叫做map(在map头文件中)。用map可以实现一个“数组” arr,这个数组的下表就是单词,保存的内容就是单词出现的次数。比如有一个单词叫buaa,那么通过map定义的“数组”,你可以实现arr["buaa"]++;这个操作。这个“数组”叫做map容器,可以当数组一样使用。定义一个map容器很简单:map的用法建议参考C++ primer。

map<string,int> wordMap;

  还有一个问题是怎么样保存应该输出哪个单词,在这里我是用了另一个map<string, string>保存的。就是所有的单词全换成小写,作为下标。对于某个单词输出的时候,输出的值是该单词在第二个map对应的单词,以及第一个map里对应的次数。

  排序输出

  在这里你可能需要先了解vector头文件中的vector,utility头文件中的pair,以及刚才提到的map。这两个数据结构都在C++primer中有详细介绍,分别在P78,P306,P309。如果你不了解这3个东西,下面一段话很可能看不懂。不过没有关系,你都有整个map容器了,大不了自己写一堆代码,把map的值全遍历到一个自己的数据结构里面,然后排个序输出。下面的方法只是讲用C++的库函数省了写过多代码。

  C++里面自带sort函数,在algorithm头文件中。sort函数可以排序数组,vector,等等(我不知道能不能排序map,没有试过,因为不用考虑效率问题,当时直接把所有map的内容移到vector里面了)。因为最后的答案是<key,value>键值对,而pair就是这种形式。所以直接用pair保存每一个<单词,次数>键值对。然后放在vector中。

pair<string,int> tmp;
tmp.first=wordTrans[mapIt->first];
tmp.second=mapIt->second;

  接下来对于vector(这里vector变量名是sortArray)直接sort就好了。

sort(sortArray.begin(),sortArray.end(),Compare);

  sort函数包含3个参数,分别是排序起始的位置,排序结束的位置,以及比较函数函数名。这个比较函数是自己写的。

bool Compare(pair<string, int> a,pair<string, int>b){...}

  函数需要返回bool型,以便告诉sort,在什么情况下,我认为a<b。

  通过这种方式,只需要几行代码就能完成最后一步。工作量要小不少。

  以上就是整个作业的大体。写下来大约100行左右。如果有什么问题或者需要接一下C++ primer,可以留言或者找我们小组的成员。

Z.XML

编辑:肖俊鹏

 

 

 

posted @ 2013-09-18 23:55  Z.XML  阅读(1115)  评论(7编辑  收藏  举报