文件操作与字符处理文档格式.docx
《文件操作与字符处理文档格式.docx》由会员分享,可在线阅读,更多相关《文件操作与字符处理文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
1.题目及题目分析
1.1问题描述
在当前目录下存在文件名为“case1.in”(其中case后为数字1,不是字母i,写错提交后会判错)的文本文件,其内容为一篇英文文章(以EOF作为结束标志)。
现要求读取该文本文件内容,统计该文本文章中每个单词出现的次数,并输出出现次数最多的前5个单词及其出现次数(按出现次数由多到少的顺序输出,次数相同时按字典顺序输出,不足5个单词时,按序输出全部单词)。
程序中注意如下细节:
(1)空格、标点符号与回车键起到分隔单词的作用;
(2)名词缩写算一个单词;
(3)单词不区分大小写;
(4)输出时单词全使用小写;
(5)包含多段文字,单词数不超过10000,每个单词不超过20个字符;
(6)数字不算单词;
(7)文中不包含连字符及类似I’m等情况;
(如case1.in内容如下)
Iamastudent.MyschoolisSCAU.Itisa
beautifuluniversity.Ilikeit.
(在屏幕上输出结果如下)
a2
i2
is2
it2
am1
1.2功能分析
简单的说,这个实验要求我们读取一篇存储在一个文本文件中英文文章中的所有单词,然后统计其中单词出现的次数,并把其中出现最多的五个单词输出来并输出其出现的次数。
我们的任务是怎样把这篇英文文章中的单词读取出来,并把它的出现次数统计出来,并把其中出现最多的5个单词输出来。
然后我们再深度处理,按照题目要求作修改。
我们怎样才能把一个个单词读取出来,因为有些单词是不止一个字母的,我们又要怎样处理?
我们又要怎样把这不止一个字母的单词通过比较来判断是否一个单词?
还有怎样把出现次数最多的5个单词输出来,这要怎样处理?
这些是比较难处理的。
2.设计思路
1.1总体结构设计
要实现题目中的要求,我们要把程序设计成几个模块来实现。
第一个模块,就是用来读取英文文章中的单词,这就要用到文件这些知识,因为单词可能不止一个字母,所以我们先要用数组来保存,这就要用到数组的知识。
读取单词之后怎么样统计出现的次数,这又要另设一个模块。
到最后,判断出现次数最多的单词然后输出来是一个模块。
还有,在一开始要设计一个结构体来保存单词,这是一个模块。
所以,一共设计了4个模块。
其中,在第三个模块又要分开几个小方块,因为其中要处理单词分隔的时候,这里的处理是一个难点。
还有题目中不包含分隔符的情况。
我们把字母处理作为一个小方块,分隔符读取作为一个小方块,还有。
详细说明看以下内容。
1.2各个功能模块详细设计及功能模块之间关系设计
首先,我们要做好预处理指令,在首行输入#include<
stdio.h>
因为后面会用到字符串函数,所以我们还要在第二行输入#include<
string.h>
把”string.h”文件包含到文件中。
然后,因为文件中的英文文章中的单词要储存和统计出现的次数。
要同时记录这两项数据要怎样处理好呢?
没错,就是用结构体来储存,设立一个wordkeep的结构体类型,里面只需设立两个成员,第一个设立为字符串数组类型来保存文章中出现的单词,因为题目中规定每个单词的长度不超过20,所以字符数组的长度为20。
第二个设立为基本整型来保存单词出现的次数。
接着要定义变量。
因为题目中规定说单词数不超过10000,所以我们可以用一个word[10000]的结构体数组来实现。
结构体建立要放在预处理指令后面,这就是这个程序的第一个功能模块。
上述操作的代码如下图所示:
结构体建立完毕后就是主函数了,主函数包含了三个模块,包括了读取文章中的每一个字母,判读每一个单词,判断每一个单词出现的次数,把出现次数最多的5个单词输出。
这里,我用一个简单的流程图来说明一下主函数执行的流程:
上面的流程图大致的描画了实现这个实验的基本操作,基本思路,那么,我们现在就按照这个思路来编写程序。
以上的操作缺一不可且不能换序,因为你读入了一个单词才能分离一个单词,才能判断出现过没有,才能统计出现次数,才能准确的排序输出。
我们一定要仔细编写程序,因为每一个环节出差错,都会影响到下一个环节,牵一发而动全身。
第二个模块是单词的输入,这里要用到文件的知识,因为只是读取,所以我们只需要用一个fopen(文件名,使用文件方式)的调用方式打开文件,其中文件名已经是题目规定了的,是case1.in,而使用文件方式是只读,也就是r。
因为下面还要用到一些变量,所以我们预先在第一模块就把它们设置好先,其中,i,t和j是用来计数的,m和f是用来判断真假的,k用来统计所出现单词的次数(包括重复出现的),具体操作代码如下:
我们打开了文件,然后就是读取文件中的单词,这里要用到fgetc(fp)的调用形式,即从fp指向的文件中读入一个字符。
我们在当读取字母不是结束符号的时候就开始读入。
因为题目要求所统计单词不分大小写,所以,我们统一把所读取的字母先转化为小写字母,那么,我们在判断了所读入字母是否为结束符号之后,还要判断一下所读取字母是否为大写字母,如果是大写字母的话,就转化为小写字母。
这里还有一个问题,就是关于输入字符的类型。
这里,输入的字符可以分成两种类型。
一种是英文字母,一种是分隔符。
题目中说空格、标点符号与回车符起到分隔单词的作用,所以分隔符又分成空格、标点符号和回车符。
当我们读入字符时,一定要做好对分隔符的处理。
好了,现在先说说当读取到的是英文字母的时候,我们先统一转化为小写字母,然后用一个字符数组来先储存着。
因为有些单词不止是由一个单词组成的,那么,我们就要判断下一个读入字符是否为分隔符,如果所读取的字符不是分隔符的话,我们继续用那个字符数组来保存读入的字母,以此类推下去,注意保存时的下标要依次增加就行了。
这样一直直到出现了分隔符,因为所有的标点符号都是分隔符,如果我们逐一书写出来会比较的麻烦,刚好题目说明了不包含连字符,所以我们把出现连字符和下一个输入字符为回车键假设为假,然后除连字符之外的标点符号就为真了。
我们这样做要先设一个控制真假的变量,上面已经设之为f。
出现了分隔符,我们怎么处理已经储存在一个字符数组中的单词呢?
好,我们把一个单词的最后一个字母后面再加一个空字符,宣告给系统知道这个单词读取结束了,然后与之前出现的单词相比较,看有没有相同的,比较前还要做一个判断,判断是否已经有输入的单词了,如果还没有输入单词,那就不用比较了,如果已经有了输入单词,就开始比较,比较时可以直接用字符数组和字符数组比较,就是用在主函数中用来临时保存保存单词的字符数组和在结构体中用来正式保存单词了字符数组来比较。
比较时我们可以用字符串函数中的strcmp函数来进行比较,如果比较出来的值为0,也就是两个单词相同,这时候,就令在结构体中保存这一单词的变量中的整型常量这一成员加一。
如果比较的时候没有一个单词是相同的,那就要另外增加一个统计项,把这个单词复制到结构体中保存,令其出现次数为一。
还有,我们在统计单词时注意要统计一共有几个单词,要实现这个我们可以设置一个整型常量,在每次新增统计项时令这个常量加一,我们在下面就把它设为了k,如下图所示。
这样一直读取下去,直到读取到结束符号,即EOF。
这时,我们要处理的是把出现次数最多的5个单词输出。
这时候,我们只需比较它们的出现次数,出现次数在结构体中有保存。
因为可能文章中的单词不超过5个,所以我们的条件务必要写成i<
k&
&
i<
5。
然后通过冒泡排序把出现次数最多的排在第一位,但是如果出现次数相同,我们怎么按照字典顺序排序呢?
这样的话我们通过比较字符的大小来排序,因为ASCII码的排序是按照字典排序来排序的,所以我们可以通过比较字符在ASCII码中的值的大小来比较顺序的前后。
排序结束后就依次输出,输出后要记得关闭数据文件,就是在return0前面写上fclose(fp)。
就这样,这个程序就基本上完成了。
1.3数据结构的设计
1.4界面设计
综上所述,实验所设计的界面如下简图所示:
其中,主函数中有一个特殊的处理(判断除去连字符之外的所以标点符号),如下图所示。
3.编程实现
要实现编程,首先要建立一个wordkeep的结构体,这是为下面保存单词打下铺垫,我们还要建立一个结构体数组,如下左图所示:
然后就是设好变量和读入数据,如上右图所示:
然后,就是判读文章中读入的字符,该操作的流程图如下图所示:
这一模块的主要功能模块的代码段片段及注解如下所示:
最后,就是排序输出:
就这样就可以实现编程了。
4.运行测试
现在,我们用一组数据来测试一下,就用题目中的数据来测试吧。
我们先建立一个case1.in的文件放在保存改程序的目录下。
case1.in的位置和内容如下图所示:
我们先打开编程软件,这里,我用的是C-Free5.0,我们先把程序代码输进去,如左图所示。
我们定义了文件指针,以读的方式打开文件。
然后开始读入字符。
第一个读入的字符是“I”,因其是大写字母,所以在第17行被转化为小写字母i。
在19行字母i被存入字符数组w中,其下标为0,计数变量i变为1,字符标志为1(即所读入字符为英文字母)。
然后转回第15行再读入字符“”(空格,下同),转到17行判断,不符合条件,转到18行判断,不符合条件,转到22行判断,不符合条件,转到25行,符合
条件,
再跳到15
读取下一个结构体变量,令j为0,比较保存在结构体中的单词的出现次数,如果出现次数较多的话,把其保存在结构体数组中的位置交换。
如果出现的次数不大于后面那个单词出现的次数,那么有可能是等于或小于,当出现次数相同的时候,我们比较单词的大小,即从首位开始比较其ASCII码的大小,这样就可以实现次数相同时按字典顺序输出,最后程序出来的结果如题目中所示。
为了能比较直接地观察程序运行的情况和各变量的变化,我专门设计了一个各变量各时间变化的表格,如下所示:
行数
变量
17
18
19
15
22
25
27
28
33
35
ch
I
i
a
1
m
j
k
t
f
30
……
2