一、时间分配
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 { 8public: 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 22public: 23 void tianjia(string danci); //向单词链表里添加一个单词的函数 24 bool panduan(string danci); //判断单词是否存在函数 25 void shuchu(); //输出文件的内容函数 26 dancibiao();//构造函数 27private: 28 Danci *first; //Danci类类型的first指针指向链表的头部 29 Danci *last;//Danci类类型的last指针指向链表的尾部 30 int length; //文件的长度 31 int total; //单词的总个数 32 }; 33 class wenzhang //定义一个wenzhang类 34 { 35string txt; 36dancibiao mywords; 37public: 38 void file(); //输入 39 void top();//输出 40 void Run(); 41 }; 42 dancibiao::dancibiao() //初始化单词链表为空链表 43 { 44first=new Danci(" "); 45first->next=NULL; 46last=first; 47length=0; 48total=0; 49 } 50 void dancibiao::tianjia(string danci)//实现添加单词的函数 51 { 52if( !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 { 63Danci *p=first->next;//让p指向first的下一个单词 64total++; 65while(p!=NULL) //p的内容不为空 66{ 67 if( p->danci == danci ) //如果p所指向的单词和当前单词一样则这个单词的数量加1 68 { 69 p->num++; 70 return true; 71 } 72 p=p->next; //指针下移 73} 74return false; 75 } 76 void dancibiao::shuchu()//实现dancibiao类里面的shuchu函数,输出频率最高的前十个单词 77 { 78int n=10; 79if( length < n) //如果文件中单词的数量少于10个则输出提示信息 80{ 81 cout<<"\n不同的单词不足10个\n"; 82} 83cout<<"单词"<<" "<<"出现次数"<<" "<<"频率"<<endl; 84for( 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 109ifstream file(file_name.c_str(), std::ifstream::binary);110111if(file)112{113114file.seekg(0, file.end);115const int file_size = file.tellg();116char* file_buf = new char [file_size+1];117memset(file_buf, 0, file_size+1);118file.seekg(0, ios::beg);119file.read(file_buf, file_size);120 121 122 if(file)123{124 fileData.append(file_buf);125}126else127{128 std::cout << "error: only " << file.gcount() << " could be read";129 fileData.append(file_buf);130 return false;131}132file.close();133delete []file_buf;134}135else136{137return false;138}139return 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 {148int i=0;149while( 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 {169cout<<"\n出现频率最高的前十个单词: \n";170mywords.shuchu();171 }172 void main()//主函数173 { 174wenzhang wz;175wz.file();176wz.Run();177wz.top();178 }
四、运行结果