C Primer Plus(5版)第8章编程题1_文件I/O实现2

小伙伴们,对C语言编程有疑问的,可以加微信交流:poo_poo或者扫描我的头像,验证时请注明是“知友”

之前在 C Primer Plus(5版)第8章编程题1_重定向实现 - 知乎专栏C Primer Plus(5版)第8章编程题1_文件I/O实现1 - 知乎专栏 这两篇文章中,如何实现统计一个文件中的字符个数,我使用了重定向技术和文件I/O函数来统计的方法。重定向技术简单,直接调用了系统的能
力,所以代码量也不多。使用fseek和ftell函数也很简单,完全使用了这两个函数的自身的能力。本文再使用第三种方法,是文件I/O函数的getc函数来实现文件字符数的统计。

一、题目描述

本题是第8章编程题的第一道题,题目如下:

4232298-707c09bce634c63a.png
image

二、题目及思路分析

从题述来看,有如下几个关键点:
1.有这么一个文本文件
2.读入文件中的文本
3.统计文件中字符数
4.判断文件的结尾
下面再给出这4步的每一步的解决思路。

1. 有这么一个文本文件
这个好解决。我事先准备好了一个文本文件,文件名是author.txt,里面准备了一些字符,如下:
weibo: http://weibo.com/520JDH
zhihu: http://zhihu.com/people/520WX
CSDN: http://blog.csdn.net/kelehaier

2. 打开文件
这是要解决的第一个技术点。使用文件I/O包中的fopen函数打开文件,最后记得一定要fclose这个文件。

3. 统计文件中字符数
这是要解决的第二个技术点。如果有一种方法,能够逐一地读取每行的每一个字符,并且每读完一个字符,字符计数器就自增1,那么我们的目的就达到了。在文件I/O函数包中,
getc函数就可以达到这个目的。getc函数的功能是逐一读取文件中的每一个字符,当然包含每行的结尾的换行符,它需要一个文件指针作为参数。

4. 判断文件的结尾
这是要解决的第三个技术点,即,如何判断getc函数已经读到了文件末尾。在C中,针对不同的系统,统一以一个“EOF”来表示文件的末尾。这个“EOF”如果你到头文件中查看其
定义,会看到可能是一个整数值,比如“-1”。getc()函数遇到文件末尾后就会返回“EOF”。本程序在getc函数达到文件末尾后,打印出EOF,看看在我的编译环境中EOF的定义值
是什么。

三、代码实现

根据上述分析,主要代码如下:

pFile = fopen("author.txt","r");
while( (ch = getc(pFile)) != EOF)
{
    printf("%d   ", ch);
    count++;
}
    putchar('\n');
    printf("文件结尾是:  %d\n", ch);

代码以文本模式打开文件,getc函数使用pFile这个文件指针作为参数,从pFile指向的文件中逐一读取字符,在每读取一个字符时,计数器count自增。当文件位置指示器达到文件
末尾时,也就是getc函数读到文件末尾时,while循环退出。此时计数器count的值便是文件中字符的个数。由于此时文件位置指示器指向结尾,在退出while循环后,代码会将EOF对应的值打出。
完整的代码下载地址:

C Primer Plus(5版)第8章编程题第1题_getc函数实现

扫描二维码关注公众号,回复: 9855538 查看本文章

四、运行结果

本程序的运行环境如下:
OS:Windows XP sp3
编译器:TDM-GCC 4.9.2 32-bit Release
运行结果如图:

4232298-0d6ef155cb694b0d.png
image

从运行结果来看,统计出的字符数是97,并且打印出的EOF的值为-1.在我的编译环境中,EOF的值被定义为-1.也许在你的编译环境中,EOF的定义值和我不一样。

现在我将代码中的文件打开模式修改下,如下:

pFile = fopen("author.txt","rb");

使用二进制模式打开文件,那么再来运行下,看看结果如何:

4232298-56281911e18e70ed.png
image

比较两种不同的文件打开模式,一个是文本打开模式,一个是二进制打开模式,发现使用getc函数统计出的字符数不一样!
为了解释这种现象,我就拿本例的文本文件的第一行的内容“weibo: http://weibo.com/520JDH” 画个示意图吧,如下:

4232298-f73a69a5c2d85866.png
image

这个示意图是在Windows上,文件内容的存储方式示意图。可以看到,一行的换行符其实是由两个字符组成的:一个是\r,一个是\n。如果以二进制模式打开这个文件,那么,对于
getc来说,它将看到两个字节,一个是“00001101”(\r的二进制),一个是“00001010”(\n的二进制),因此getc函数在每行末尾会统计到这两个字符。
如果以文本模式打开这个文件,那么C实现会做一个转换,将“\r\n”两个字符转换成一个字符“\n”,我再画个示意图如下:

4232298-b469008aabe35b3f.png
image

此时getc只能看到一个“00001010”(\n的二进制),因此在每行的末尾,getc函数只会统计到“\n”这一个字符。因此在最终的统计结果中,以文本模式打开统计的字符数比以
二进制模式打开统计的字符数要少两个,少的这两个就是“author.txt”中第一行和第二行末尾的“\r”字符。

由于在linux上,一般而言,一行的结尾只有换行“\n”这一个字符,因此如果运行环境是linux,那么不管是以文本模式打开还是二进制模式打开,统计到的字符数都是99.有条件
的朋友可以自行试下。

五、技术点

本文给出了一种统计文件字符数的方法,关键技术点是getc函数。如果运行环境是Win的话,要注意文本模式和二进制模式的区别。

六、总结

目前为止,为了实现统计一个文件中的字符数的方法,使用了三个不同的技术手段,一个是重定向技术,一个是文件I/O包中的fseek和ftell,最后一个是I/O包中的getc函数。三
种方法各有优缺点。朋友们今后需要在自己的项目中实现这一小功能,可以考虑这三种方法。

发布了214 篇原创文章 · 获赞 90 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/kelehaier/article/details/88888626