个人第二次作业

0前言

本次作业要求做一个词频统计的软件,功能简单来说是实现英文文章的单词总数,以及每个单词出现次数的统计。

编程语言语言:C++

工具:CodeBlocks

git地址:https://git.coding.net/Vrocker/wf.git

一、主要功能

0.简述:

题目要求总共为四部分,通过对这四部分功能需求的研究,可以将主要功能细分成以下部分:

1.可以读入本地txt格式的文件,要求内容是英文书籍或者文章。

2.统计文件中不重复出现单词的总数,并输出。

3.统计文件中英文单词的词频,即出现的单词以及这个单词出现的次数,并且降序输出。

4.要求在命令提示符中直接控制程序,即输入相应参数实现相应的功能。

5.支持单一文件,同时支持指定文件夹下的所有文件中英文单词的词频统计。

6.在多文件统计时只输出出现次数最多的十个单词。

二、设计思路

  要实现题目要求的功能,我首先想到的是用数组或者链表来进行操作:

  首先读入输入的文本文件,将文本文件的各个字符包括标点符号等逐一放进数组中。然后设置一个指针从头开始进行遍历,一旦遇到标点或者空格的时候(我认为“-”连接的两个或多个英文单词应该算作一个单词,所以“-”不用排除掉)就可以分割单词,将这个单词保存到另外一个数组中。然后再设置另外一个指针,对新数组进行遍历,统计每个单词出现的次数,以及这个单词本身。最后利用排序算法,例如冒泡排序,进行降序排序。这样就可以大致实现主要的功能。

  但我在查阅资料的时候,我看到一篇博客名为”【tips】【词频统计】中可能用到的资源,以C++为例“的博客,网址是:http://www.cnblogs.com/Z-XML/p/3329234.html(真的很感谢这位作者)。看完这篇博客我了解到在C++中有一个MAP容器,可以更好更简单,而且更快的完成想要的功能。因为之前接触C++的时候,并不了解map容器,所以便开始了学习的过程。同时在这篇博客中我了解到利用vector以及自带的sort函数可以排序数组。这样就大大减少了工作量。但是由于之前我也没接触过这些,所以也要开始学习这些对我来说新的概念和方法。所以我放弃了最开始选择的设计思路,改用这个来设计我的程序。

三、难点

1.参数

  功能要求通过命令提示符输入相应的参数可以直接进行操作。这样的设计方法,之前我并不了解。所以开始查询资料,找解决方案。因为选择了C++进行编程,所以也开始看相关的C++书籍。这个功能花费了我相当多的时间来解决。首先的难题是不知道怎么可以获取到这些参数,同时也不清楚怎么样对参数进行判断,以便进行不同的操作。

  在学习之后,知道了C++中可以用int main(int argc, char* argv[])定义主函数,从而直接实现参数的功能。部分代码如下:

 1     for(int i=1; i<argc; i++)//用于接受从命令提示符传递进来的参数
 2     {
 3         str = argv[i];
 4         if(str=="-s")//如果从命令提示符传递的第一个参数是“-s”执行以下操作
 5         {
 6             char const *a = "g:\\";
 7             char const *b = argv[i+1];
 8             std::string const& cc = std::string(a) + std::string(b);
 9             char const *c = cc.c_str();//将两个char进行拼接,以便传入fin.open函数中
10             fin.open(c);
11             break;//跳出判断
12         }
13         else  if(str=="floder")//如果从命令提示符传递的第一个参数是floder执行以下操作
14         {
15             system("dir /b /a-d G:\\floder\\*.* >d:\\allfiles.txt");//读取指定文件夹下的所有txt文件
16             for(int j=2; j<argc; j++)//将所有的txt文件写入流文件
17             {
18                ............//此功能未能实现
19             }
20         }
21         else//当传递的第一个参数是txt文件的文件名时
22         {
23             char const *a = "g:\\";
24             char const *b = argv[i];
25             char const *d = ".txt";
26             std::string const& cc = std::string(a) + std::string(b) + std::string(d);
27             char const *c = cc.c_str();
28             fin.open(c);
29         }
30     }    

2.拼接char*

  要求的功能中,要实现在命令提示符输入wf和书名来实现词频统计。而在我设计的程序中,要用到被统计文件的实际地址。例如"c:\\a.txt"。但是文件的名字又是不确定的所以我在这里要用到拼接char*来实现。在查询大量资料后,发现可以实现。代码如下:

1         if(str=="-s")//如果从命令提示符传递的第一个参数是“-s”执行以下操作
2         {
3             char const *a = "g:\\";
4             char const *b = argv[i+1];
5             std::string const& cc = std::string(a) + std::string(b);
6             char const *c = cc.c_str();//将两个char进行拼接,以便传入fin.open函数中
7             fin.open(c);
8             break;//跳出判断
9         }

3.去除标点

  要实现统计词频的功能,标点就一定会影响统计。所以要除去标点,才能正确的统计单词,并且最后完整正确的输出。为此定义了一个函数,来实现这个功能。代码如下:

1 void StringToLower(string &theString)//将字符串转化成全小写
2 {
3     int nLen = theString.length();
4     for(int i = 0; i < nLen; i++)
5     {
6         theString[i] = tolower(theString[i]);
7     }
8 }

  并且在输入文本之后,调用这个函数,将不相关的符号排除。代码如下:

1     set<char> ignoreSet;//除去标点符号或者会影响判断单词等符号
2     ignoreSet.insert(‘,‘);
3     ignoreSet.insert(‘.‘);
4     ignoreSet.insert(‘?‘);
5     ignoreSet.insert(‘:‘);
6     ignoreSet.insert(‘!‘);
7     ignoreSet.insert(‘;‘);
8     ignoreSet.insert(‘\‘‘);
9     ignoreSet.insert(‘"‘);

4.转换大小写

  我在第一次测试程序的时候,发现自己犯了一个错误。就是大小写没有转换,导致同样的单词只是大小写不一样,会有两个结果。这显然不符合题目的要求。所以为了让大小写统一,这里把统计到的所有单词都转化成小写字母。这样就不会有问题。代码如下:

1 void StringToLower(string &theString)//将字符串转化成全小写
2 {
3     int nLen = theString.length();
4     for(int i = 0; i < nLen; i++)
5     {
6         theString[i] = tolower(theString[i]);
7     }
8 }

5.排序输出

  最后要对统计过的单词以及出现的次数,以次数为标准降序排列输出。这里就用到了排序的函数。最开始,我想用冒泡排序或者其他相应的算法进行。但是在了解C++中各种排序的方法之后。我了解到C++自带一个sort函数可以用于排序。所以在这里我选择这个方法。在看了一些用map容器最后进行排序的相关代码之后,我发现这些代码最后大部分都是把map转化成vector之后再进行排序。但是对于这个知识点我之前也是没有接触过。所以再进行学习之后,模仿同样方法的排序代码尝试进行自己编写。代码如下:

 1     struct CmpByValue
 2 {
 3     bool operator()(const PAIR& lhs, const PAIR& rhs)
 4     {
 5         return lhs.second > rhs.second;
 6     }
 7 };
 8 ..................
 9     vector<PAIR> wmap_vec(wmap.begin(), wmap.end());
10     sort(wmap_vec.begin(), wmap_vec.end(), CmpByValue());

  利用wmap_vec.size()可以直接输出总数。

  这时候每个单词存放在对应的wmap_vec[i].first 中。而出现的次数存放在对应的wmap_vec[i].second中。再用一个for循环就可以输出。

 1     float sum=0;
 2     for (int i = 0; i != wmap_vec.size(); ++i)//利用map输出总字数
 3     {
 4         sum=sum+1;
 5     }
 6     cout<<"total    "<<sum<<"  words"<<endl<<endl<<endl;
 7     for (int i = 0; i != wmap_vec.size(); ++i)//利用map输出每个单词以及其出现次数
 8     {
 9         cout << left << setw(50) << wmap_vec[i].first << wmap_vec[i].second << endl;
10     }

四、功能测试

1.

2.

3.

  这个部分支持命令行输入存储有英文作品文件的目录名,批量统计。这个功能花费了我很长的时间来做。但是还是没有做好。试了很多方法,但是都没有成功。上述代码有出现str = argv[i];else  if(str=="floder");判断参数成功的时候试过设置一个flag,当主函数运行到输出部分的时,如果flag正确则多次输出结果。但是没有成功。

五、总结

  刚开始我看到这个题目的时候,第一感觉是挺简单的。逻辑不复杂,而且应该比较容易实现。所以一直没觉得会花费我太多时间。但当我真正开始着手写代码的时候发现,可以用更简单便捷的方法实现。所以我就开始研究这个新的方法。因为觉得代码量并不大,所以又一次估算时间应该没有多久。然而,写着写着我开始发现自己的知识掌握的太不牢固,同时也发现自己想要用的这个方法里面,有太多东西是我之前没有接触过的。但是既然选择了这个方法,况且这个方法看起来确实比较简洁,我就硬着头皮边写边学。

  首先map容器和vector之前我并不知道。所以两个知识点我花了相当大的时间来处理。之后参数的相关知识也是一知半解,再查了很多资料之后才开始着手编写,这个环节花费的时间也不少。虽然知识点不多,但是由于没有实际编写过,所以在调试,测试的过程中出现了很多很多的问题。同时,char*的拼装,也是在查阅资料之后在知乎看到一个回答,才让我很好的解决。这些只是花费时间比较多的环节,实际上每个步骤我都花费了相当长的时间。总结来看,预估的时间远远小于我真实花费的时间。

  通过这次编写程序,让我最感触的就是预估的时间可能会远远低于花费的时间。一个看上去不难的程序,在编写的过程中也会遇到很多难题。同时,这次编写程序让我开始知道自己掌握的知识点,远远不够,需要不断的学习同时不断地练习才能保证熟练的掌握一门语言。

PSP表格


分类


预计时间(分钟)


实际时间(分钟)


实际总时间(分钟)


时间差(分钟)


功能一


90


95


155


65


测试1


60


功能二


150


150


240


90


测试2


90


功能三


120


240


330


110


测试3


90


功能四


180


90


150


-30


测试4


60


总体调试


60


90


90


30

时间: 2024-10-12 05:48:40

个人第二次作业的相关文章

解题报告——2018级2016第二学期第二周作业

解题报告——2018级2016第二学期第二周作业 D:迷宫问题 题目描述: 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线. 输入 一个5 × 5的二维数组,表示一个迷宫.数据保证有唯一解. 输出 左上角到右

马哥linux 培训第二周作业

注意:第二周作业,请将以下题目整理在51cto博客当中,完成后请将对应的博文链接地址提交在答案栏中,提交格式如下:学号+姓名+博文链接地址eg:1+张三+http://mageedu.blog.51cto.com/4265610/1794420 本周作业内容:1.Linux上的文件管理类命令都有哪些,其常用的使用方法及其相关示例演示. 文件管理的命令有cp.mv.rm 复制命令:cp 用法: cp [-adfilprsu] 来源文件(source) 目标文件(destination) cp [o

第二次作业 孙榜婷

2.9 设有如下语句,请用相应的谓词公式分别把它们表示出来: (1) 有的人喜欢梅花,有的人喜欢菊花,有的人既喜欢梅花又喜欢菊花 . 解:定义谓词 P(x):x是人 L(x,y):x喜欢y 其中,y的个体域是{梅花,菊花}. 将知识用谓词表示为: (∃x )(P(x)→L(x, 梅花)∨L(x, 菊花)∨L(x, 梅花)∧L(x, 菊花)) (2) 有人每天下午都去打篮 解:定义谓词 P(x):x是人 B(x):x打篮球 A(y):y是下午 将知识用谓词表示为: (∃x )(∀y) (A(y)→

牛老师第二次作业

namespace 第二次作业{    class RandomNumber    {        public int Add(int x, int y)        {            return x + y;        }        public int Sub(int x, int y)        {            return x - y;        }        public int Mul(int x, int y)        {    

Linux+Python高端运维班第二次作业

Linux+Python高端运维班第二次作业 1.列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可. [[email protected] ~]# who |cut -d" " -f1|uniq (unknown) root test1 [[email protected] ~]# who |cut -d" " -f1|sort -u root (unknown) wangyanglin 2.取出当前系统上被用户当作其默认shel

第二周作业补交(请老师看一下)

#include<stdio.h> #include<math.h> int main(void) { int money,year; double rate,sum; printf("Enter money:"); scanf("%d",&money); printf("Enter year:"); scanf("%d",&year); printf("Enter rate:

耿丹16-1第二次作业

-- Deadline: 2016-09-23 23:00 pm -- 作业内容:https://edu.cnblogs.com/campus/bjgygd/Sixteen-One/homework/85 -- 第二次作业总结: 1. 总共5位同学未按时提交,且目前未交. 2. 大部分同学都注意了代码的缩进格式,希望继续保持! 3. 希望同学们下节课作业可以使用博客中自带的代码编辑器,养成良好的代码编写风格! 周刘晋源同学已经开始使用了,特此提出表扬! 4. 大家学习了变量类型的定义,以后会遇到

第二次作业: 二维数组

高级语言程序设计报告   实习题目 第二次作业: 二维数组 P228计算机双学位第8章实验题:学生成绩管理系统 l 在上次作业的基础上,改为每学生2门课,用二维数组编程实现相应功能,相应功能所有涉及分数的均需可以处理每门课程分数及每个学生课程总分. l 涉及到排序的,均需提供冒泡及选择两种排序方法,可增加菜单项. l 功能5中按学号查询学生排名及成绩,要求用折半法,为此你的学生数据可以多一点. l 数组中可以事先有数据(省却每次输入数据浪费时间),为此输入数据菜单可以改造为增加数据菜单. l 在

对于第二次作业的不懂之处

助教老师您好: 对于第二次作业这个计算器,我花费了四个白天的时间,做了N多次,由于我的基础太差,我曾最大限度地在控制台做到了能随机产生数字,和四则算法,(我能做的最大限度)而难处在于我不能让用户对这四则算法算出结果,更不要说正确率了,而且它不能识别除法时除数不能为零. 在窗体程序中我做出来了form框架,然而我在写完代码后发现TextBox1和TextBox2竟然不会随机产生数字,我也像大多数同学一样,照着课本上的例题做修改,但是我却不如人家,我并没有用窗体完成,而且在窗体中我无法让用户选择一种

2017秋-软件工程第二次作业

本周因为个人缘故,参加社团活动作业没能及时完成.对此我表示,做过就不后悔,至少我觉得生活是丰富多彩的,错过的时间就应该努力赶上!夜深人静的时候总是可以让人反省自己.本次作业我只实现了第一个功能和第二个功能的部分.对此我表示很不满,但是时间紧迫.个人能力有限,以至于自己没能让自己的软件看起来完美. 第二次作业的内容非常有趣,这也是我一直想做的一件事情,统计一篇文章里的字词.我知道自己的编程能力较差.距离完成提交时间很近,自己手写全部是不能及时按照约定提交的,于是就尝试借鉴前人的代码.第一晚的努力各