编程实现统计一篇英文文章中各个单词出现的频率,输出频率最高的前十个单词的频率

一、时间分配

    2月22日 晚7:00~8:30  设计思路 确定编程语言

    2月23日 晚7:00~8:30 编写代码

    2月26日 晚8:00~9:00 编写代码

    3月1日   晚7:00~8:30 调试程序

    3月2日   晚8:00~11:00 写博客

     3月3日  晚8:00~9:00 写博客 总结

二、总结

    设计思路:分三个模块

    1、读文件模块

     2、词语分析模块

     3、排序

     其实老师布置题目的当天晚上就在想这道题了,但是不知道用数组,还是结构体,还是链表等等,本来写程序就不是强项,拿出以前学过的C++课本来复习了一下指针那部分知识。尝试着开始编写代码,读文件编写出来了,接下来是怎么把单词一个一个分出来,以前上编译原理课时写过一个词法分析程序,借鉴一下就可以;然后再用个排序。这是最初的想法。调试当中出现的很多问题,在苏林东同学的帮助下,最后有了结果,他也教我了很多思想。收获挺多的,这个程序我都加了注释,应该很明了了。具体用了类类型的指针;然后用链表进行分词;链表排出频率最高的前十个词。分析它的效率,当文件为65k时,用了3s;当文件为450k时,用了19s.与其它同学编写用的数组或者java写的效率都低点,有待自己进一步改进。

三、程序代码

  1 #include <iostream>
  2 #include <string>
  3 #include <ctype.h>
  4 #include <fstream> 
  5 using namespace std;
  6 class Danci                  //定义一个单词类
  7 {
  8     public:
  9         int num;             //记录单词的数量
 10         string danci;        //定义一个字符串变量
 11         Danci *next;         //Danci类的指针
 12         Danci(string danci1) //构造函数
 13         { 
 14             num=1; 
 15             danci=danci1;
 16             next=NULL;       //开始时next指向空
 17         }
 18 };
 19 class dancibiao            //定义一个dancibiao类
 20 {
 21                                                              
 22     public:
 23         void tianjia(string danci); //向单词链表里添加一个单词的函数
 24         bool panduan(string danci); //判断单词是否存在函数
 25         void shuchu();       //输出文件的内容函数
 26         dancibiao();          //构造函数
 27     private:
 28         Danci *first;         //Danci类类型的first指针指向链表的头部
 29         Danci *last;          //Danci类类型的last指针指向链表的尾部
 30         int length;   //文件的长度
 31         int total;    //单词的总个数
 32 };
 33 class wenzhang         //定义一个wenzhang类
 34 {
 35     string txt;
 36     dancibiao mywords;
 37     public:
 38         void file(); //输入
 39         void top();//输出
 40         void Run();
 41 };
 42 dancibiao::dancibiao()       //初始化单词链表为空链表
 43 {
 44     first=new Danci(" ");
 45     first->next=NULL;
 46     last=first;
 47     length=0;
 48     total=0;
 49 }
 50 void dancibiao::tianjia(string danci)//实现添加单词的函数
 51 {
 52     if( !panduan(danci) )            //单词不存在
 53     {
 54         Danci *node=new Danci(danci); //动态分配node结点的内存,node指向新danci的地址
 55         last->next=node;               //以下三行是插入新节点,也就是把新单词添加到单词链表中
 56         last=node;
 57         last->next=NULL;
 58         length++;                      //单词链表的长度增一
 59     }
 60 }
 61 bool dancibiao::panduan(string danci)//判断单词函数
 62 {
 63     Danci *p=first->next;      //让p指向first的下一个单词
 64     total++;                    
 65     while(p!=NULL)             //p的内容不为空
 66     {
 67         if( p->danci == danci )  //如果p所指向的单词和当前单词一样则这个单词的数量加1
 68         {
 69             p->num++;
 70             return true;
 71         }
 72         p=p->next;            //指针下移
 73     }
 74     return false;
 75 }
 76 void dancibiao::shuchu()      //实现dancibiao类里面的shuchu函数,输出频率最高的前十个单词
 77 {
 78     int n=10;                  
 79     if( length < n)           //如果文件中单词的数量少于10个则输出提示信息
 80     {
 81         cout<<"\n不同的单词不足10个\n";
 82     }
 83     cout<<"单词"<<"             "<<"出现次数"<<"                 "<<"频率"<<endl;
 84     for( int i=0; i<n; i++ )
 85     {
 86         Danci *p=first->next;
 87         string str=p->danci;        //把p所指向的单词赋给一个字符串变量str
 88         int cishu=p->num;           //把这个单词的数量赋给cishu这个变量
 89         Danci* pcishu=p;            //把p赋给Danci类型的另一个指针pcishu
 90         while(p!=NULL)              //p不为空
 91         { 
 92             if( p->num > cishu)     //如果p指向的单词的数量大于cishu
 93             {
 94                 cishu = p->num ;    //以下三行是把p的内容给了pcishu
 95                 str=p->danci;
 96                 pcishu=p;
 97             }
 98             p=p->next;             //指针下移
 99         }
100         pcishu->num=0;
101         cout<<str<<"                 "<<cishu<<"                   "<<1.0*cishu/total<<endl;
102     }
103 }
104 
105 bool readFileToString(string file_name, string& fileData)//把文件以字符串的形式显示出来
106  {
107  
108 
109     ifstream file(file_name.c_str(),  std::ifstream::binary);
110     
111      if(file)
112      {
113          
114          file.seekg(0, file.end);
115          const int file_size = file.tellg();
116          char* file_buf = new char [file_size+1];
117          memset(file_buf, 0, file_size+1);
118          file.seekg(0, ios::beg);
119          file.read(file_buf, file_size);
120  
121 
122         if(file)
123          {
124              fileData.append(file_buf);
125          }
126          else
127          {
128              std::cout << "error: only " <<  file.gcount() << " could be read";
129              fileData.append(file_buf);
130              return false;
131          }
132          file.close();
133          delete []file_buf;
134      }
135      else
136      {
137          return false;
138      }
139      return true;
140  }
141 void wenzhang::file()
142 {
143    readFileToString("d:/chizhenzhen.txt", txt);
144    cout<<"文章为:\r\n"<<txt<<endl;
145 }
146 void wenzhang::Run()
147 {
148     int i=0;
149     while( i<txt.length())
150     {
151         string temp;
152         while( !isalpha(txt[i]) && i<txt.length())//isalpha函数判断字符txt[i]是否为英文字母
153         {
154             i++;             
155         }
156         while( isalpha(txt[i]) && i<txt.length())//如果参数是字母字符
157         {
158             temp=temp+txt[i];
159             i++;
160         }
161         if(i<txt.length())
162         {
163             mywords.tianjia(temp);
164         }
165     }
166 }
167 void wenzhang::top()
168 {
169     cout<<"\n出现频率最高的前十个单词: \n";
170     mywords.shuchu();
171 }
172 void main()//主函数
173 { 
174     wenzhang wz;
175     wz.file();
176     wz.Run();
177     wz.top();
178 }

四、运行结果

 

 

posted @ 2014-03-03 22:12  真真-是我  阅读(1476)  评论(1编辑  收藏  举报