作业3词频统计
(1). 实现一个控制台程序,给定一段英文字符串,统计其中各个英文单词(4字符以上含4字符)的出现频率。
答:
从文件读取 | 遍历字符串 | 大写转小写 | 将句子分隔成一个个单词 | 判断是否为单词 | 计算单词出现的频率 | |
预估时间 | 10minutes | 10minutes | 20minutes | 40minutes | 1hours | 2hours |
实际时间 | 5minutes | 5minutes | 15minutes | 1hours | 2hours | 2hours |
在写这次作业之前我认为只是一个简单统计题,但是看了一眼老师的要求之后,就开始有点疯了。一个要求一个要求的提出来,重叠在一起,我就发现无从下手了。又是大小写不区分,又是单词的要求长度不小于4,什么什么的。我发现就这么一个简单的编程题能被老师改成这样,老师真是煞费苦心啊。既然要求这么多,我就把每个要求一个一个拆开分析,然后再试着将他们组装起来。
#include<iostream> #include<fstream> #include<cstring> using namespace std; struct Num{ int num; char *s; }; Num word[999]; int Change(char str[999])//大写转小写 { int a = 0; while (str[a] != '\0')//当str字符串未结束时将大写字母转小写 { if (str[a] >= 'A'&&str[a] <= 'Z') str[a] = str[a] + 32;//因为大写字母与小写字母的ascll码值相差32,大写转小写要加上32 a++; } return 0; } int Judge(char w[])//判断是否符合题意的单词 { for (int e = 1; w[e] != '\0';) { if(strlen(w)<4)//判断单词字长是否超过以及等于4 return -1; if (w[e] >= 'a' && w[e] <= 'z')//判断单词的首字符是否是字母 return -1; if (!((w[e] >= 'a' && w[e] <= 'z') || (w[e] >= '0' && w[e] <= '9')))//判断单词中是否有非字母数字 return -1; else e++; } return 0; } int Fre(char f[],int total ) //统计单词出现过的频率 { if (total>0) for (int i = 0; i <total; i++) { if (!strcmp(f, word[i].s)) { word[i].num++; return -1; } } return 0; } int main() { char sentence[999]; ifstream file("d://test.txt"); //读取 if (!file){ cout << "Unable to open "; exit(1); } while (!file.eof()) { file.getline(sentence,999); } file.close(); const char *delim = ",“”.' '‘’!?"; //delim是用来定义分隔符的内容 char *p= strtok(sentence, delim);//strtok函数根据分隔符分隔字符串 int n=0; int c=0; while (p) { Change(p); if (Judge(p) != -1) { if (Fre(p, n)!=-1) { word[n].s = p; n++; } } p = strtok(NULL, delim); } while (word[c].s) //输出统计结果 { cout << word[c].s<< ":" << word[c].num << '\n'; c++; } return 0; }
我按照我模块的顺序即 从文件中读取——>大写字母转为小写字母(为了不区分大小写,函数为Change)——>把句子按照分隔符分割开来(运用strtok函数)——>判断是否符合题意的单词(函数为Judge)——>计算单词出现的频率(函数Fre)。
运行出的结果:
总结:在这次编写过程中,我发现这个果然一点都不简单。说起来一套一套的,但是真正实施起来还是很有难度的。除了一个读取文件原先写过之外其他的感觉都是第一次接触。第一个大写转小写在汇编里写的很顺溜,但是在C++中是第一次写,课本中并没有提及,所以只能借助百度来解决,百度还真有,所以第二个模块解决了。分隔句子又是一个大难题,于是我再次借助百度大神来,但是百度上的答案都不一样,所以我挑了一个我最能理解方式利用strtok(char s[],const char *delim)函数来写。利用delim定义分隔符。第三个模块完成。判断单词的条件,第一判断字长不小于4,第二判断首字母是否为字母,第三判断字母中是否有非字母数字。这个是借助大神帮忙,才能够写出来,这个真的很难啊。花了我不少心血啊。第四个模块完成。然后最重点的来了,计算词频。用指针访问单词在与下一个单词比较,相同加一,知道访问到字符串末尾在结束。
将他们组合起来更是花了好长时间。
希望以后老师在布置作业的时候,能够将每一次的交作业时间用红色标注一下,不要模棱两可的给个时间!!