文件操作与字符处理
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C语言程序设计综合性实验
实验题目:文件操作与字符处理
实验班级:2011级信管专业3班
学生学号:
学生姓名:
任课老师:
提交时间:2012-02-18
华南农业大学信息(软件)学院
综合性实验A(文件操作与字符处理)实验报告
1. 题目及题目分析
1.1 问题描述
在当前目录下存在文件名为“case1.in”(其中case后为数字1,不是字母i,写错提交后会判错)的文本文件,其内容为一篇英文文章(以EOF作为结束标志)。现要求读取该文本文件内容,统计该文本文章中每个单词出现的次数,并输出出现次数最多的前5个单词及其出现次数(按出现次数由多到少的顺序输出,次数相同时按字典顺序输出,不足5个单词时,按序输出全部单词)。程序中注意如下细节:
(1)空格、标点符号与回车键起到分隔单词的作用;
(2)名词缩写算一个单词;
(3)单词不区分大小写;
(4)输出时单词全使用小写;
(5)包含多段文字,单词数不超过10000,每个单词不超过20个字符;
(6)数字不算单词;
(7)文中不包含连字符及类似I’m等情况;
(如case1.in内容如下)
I am a student. My school is SCAU. It is a
beautiful university. I like it.
(在屏幕上输出结果如下)
a 2
i 2
is 2
it 2
am 1
1.2功能分析
简单的说,这个实验要求我们读取一篇存储在一个文本文件中英文文章中的所有单词,然后统计其中单词出现的次数,并把其中出现最多的五个单词输出来并输出其出现的次数。我们的任务是怎样把这篇英文文章中的单词读取出来,并把它的出现次数统计出来,并把其中出现最多的5个单词输出来。然后我们再深度处理,按照题目要求作修改。我们怎样才能把一个个单词读取出来,因为有些单词是不止一个字母的,我们又要怎样处理?我们又要怎样把这不止一个字母的单词通过比较来判断是否一个单词?还有怎样把出现次数最多的5个单词输出来,这要怎样处理?这些是比较难处理的。
2. 设计思路
1.1总体结构设计
要实现题目中的要求,我们要把程序设计成几个模块来实现。第一个模块,就是用来读取英文文章中的单词,这就要用到文件这些知识,因为单词可能不止一个字母,所以我们先要用数组来保存,这就要用到数组的知识。读取单词之后怎么样统计出现的次数,这又要另设一个模块。到最后,判断出现次数最多的单词然后输出来是一个模块。还有,在一开始要设计一个结构体来保存单词,这是一个模块。所以,一共设计了4个模块。其中,在第三个模块又要分开几个小方
块,因为其中要处理单词分隔的时候,这里的处理是一个难点。还有题目中不包含分隔符的情况。我们把字母处理作为一个小方块,分隔符读取作为一个小方块,还有。详细说明看以下内容。
1.2各个功能模块详细设计及功能模块之间关系设计
首先,我们要做好预处理指令,在首行输入#include
然后,因为文件中的英文文章中的单词要储存和统计出现的次数。要同时记录这两项数据要怎样处理好呢?没错,就是用结构体来储存,设立一个wordkeep的结构体类型,里面只需设立两个成员,第一个设立为字符串数组类型来保存文章中出现的单词,因为题目中规定每个单词的长度不超过20,所以字符数组的长度为20。第二个设立为基本整型来保存单词出现的次数。接着要定义变量。因为题目中规定说单词数不超过10000,所以我们可以用一个word[10000]的结构体数组来实现。结构体建立要放在预处理指令后面,这就是这个程序的第一个功能模块。上述操作的代码如下图所示:
结构体建立完毕后就是主函数了,主函数包含了三个模块,包括了读取文章中的每一个字母,判读每一个单词,判断每一个单词出现的次数,把出现次数最多的5个单词输出。这里,我用一个简单的流程图来说明一下主函数执行的流程:
上面的流程图大致的描画了实现这个实验的基本操作,基本思路,那么,我们现在就按照这个思路来编写程序。以上的操作缺一不可且不能换序,因为你读入了一个单词才能分离一个单词,才能判断出现过没有,才能统计出现次数,才能准确的排序输出。我们一定要仔细编写程序,因为每一个环节出差错,都会影响到下一个环节,牵一发而动全身。
第二个模块是单词的输入,这里要用到文件的知识,因为只是读取,所以我们只需要用一个fopen(文件名,使用文件方式)的调用方式打开文件,其中文件名已经是题目规定了的,是case1.in,而使用文件方式是只读,也就是r。因为下面还要用到一些变量,所以我们预先在第一模块就把它们设置好先,其中,i,t和j是用来计数的,m和f是用来判断真假的,k用来统计所出现单词的次数(包括重复出现的),具体操作代码如下:
我们打开了文件,然后就是读取文件中的单词,这里要用到fgetc(fp)的调用形式,即从fp 指向的文件中读入一个字符。我们在当读取字母不是结束符号的时候就开始读入。因为题目要求所统计单词不分大小写,所以,我们统一把所读取的字母先转化为小写字母,那么,我们在判断了所读入字母是否为结束符号之后,还要判断一下所读取字母是否为大写字母,如果是大写字母的话,就转化为小写字母。
这里还有一个问题,就是关于输入字符的类型。这里,输入的字符可以分成两种类型。一种是英文字母,一种是分隔符。题目中说空格、标点符号与回车符起到分隔单词的作用,所以分隔符又分成空格、标点符号和回车符。当我们读入字符时,一定要做好对分隔符的处理。好了,现在先说说当读取到的是英文字母的时候,我们先统一转化为小写字母,然后用一个字符数组来先储存着。因为有些单词不止是由一个单词组成的,那么,我们就要判断下一个读入字符是否为分隔符,如果所读取的字符不是分隔符的话,我们继续用那个字符数组来保存读入的字母,以此类推下去,注意保存时的下标要依次增加就行了。这样一直直到出现了分隔符,因为所有的标点符号都是分隔符,如果我们逐一书写出来会比较的麻烦,刚好题目说明了不包含连字符,所以我们把出现连字符和下一个输入字符为回车键假设为假,然后除连字符之外的标点符号就为真了。我们这样做要先设一个控制真假的变量,上面已经设之为f。
出现了分隔符,我们怎么处理已经储存在一个字符数组中的单词呢?好,我们把一个单词的最后一个字母后面再加一个空字符,宣告给系统知道这个单词读取结束了,然后与之前出现的单词相比较,看有没有相同的,比较前还要做一个判断,判断是否已经有输入的单词了,如果还没有输入单词,那就不用比较了,如果已经有了输入单词,就开始比较,比较时可以直接用字符数组和字符数组比较,就是用在主函数中用来临时保存保存单词的字符数组和在结构体中用来正式保存单词了字符数组来比较。比较时我们可以用字符串函数中的strcmp函数来进行比较,如果比较出来的值为0,也就是两个单词相同,这时候,就令在结构体中保存这一单词的变量中的整型常量这一成员加一。如果比较的时候没有一个单词是相同的,那就要另外增加一个统计项,把这