阅读 ‧ 电子书库 警  告
小心!如果使用任何一种“w”模式打开一个已有的文件,文件内容将被删除,以便程序以一个空文件开始操作。

程序成功地打开一个文件后,fopen()函数返回一个文件指针(file pointer),其他I/O函数用这个指针来指定该文件。文件指针(比如这个例子中的fp)是一种指向FILE的指针;FILE是stdio.h中定义的一种派生类型。指针fp并不指向实际的文件,而是指向一个关于文件的信息的数据包,其中包括文件I/O使用的缓冲区信息。因为标准库中的I/O函数使用缓冲区,所以它们需要知道缓冲区的位置,还需要知道缓冲区的当前缓冲能力以及所使用的文件。这样这些函数在必要的时候可以再次填充或者清空缓冲区。fp指向的数据包中包含全部这些信息(这个数据包是C结构的一个例子,我们将在第14章“结构和其他数据形式”中讨论该主题)。

如果不能打开文件,fopen()函数返回空指针(也是在stdio.h中定义的)。如果fp为NULL,程序将退出。磁盘已满、文件名非法、存取权限不够或者硬件问题等都会导致fopen()函数执行失败。这就需要查找故障,一个小问题的查找也可能颇费周折。

13.2.3 getc()函数和putc()函数

这两个函数的工作方式和函数getchar()与putchar()非常相似,不同之处在于您需要告诉getc()和putc()函数它们要使用的文件。所以,下面的方法从标准输入获得一个字符:

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

阅读 ‧ 电子书库

但下面的语句表示从指针fp指定的文件中获得一个字符:

阅读 ‧ 电子书库

与之类似,以下语句表示将字符ch写入到FILE指针fpout指定的文件中:

阅读 ‧ 电子书库

在putc()函数的参数表中,首先是字符,然后是文件指针。

程序清单13.1把stdout作为putc()函数的第二个参数。stdout是在stdio.h中定义的与标准输出相关联的文件指针,所以putc(ch, stdout)和putchar(ch)的作用是一样的。实际上,后者一般通过前者定义。类似地,getchar()使用作为标准输入的getc()定义。

既然这样,为什么这个例子中要使用putc()代替putchar()呢? 一个原因就是要介绍putc()函数,另一个原因是通过使用stdout之外的参数,可以很容易地将这段程序改写为向文件进行输出。

13.2.4 文件结尾

从文件中读取数据的程序需要在到达文件结尾时停止。程序怎么才能知道是否己到达文件结尾了呢?如果在尝试读入字符时发现已经达到文件结尾,getc()函数会返回一个特殊值EOF。所以C程序只有在读取超出文件结尾以后才会发现文件的结尾(这是与其他一些使用专用函数在尝试读取之前检测文件结尾的语言的不同之处)。

为了避免试图读取空文件带来的问题,应该对文件输入使用入口条件循环(而不是do while循环)。鉴于getc()函数(以及其他C输入函数)的设计,程序应该在进入循环体之前尝试进行第一次读取。所以下面的设计会很好地工作:

阅读 ‧ 电子书库

阅读 ‧ 电子书库

这些语句还可以精简为下面的形式:

阅读 ‧ 电子书库

因为输入语句是while判断条件的一部分,所以将在进入循环体之前执行该语句。

应该避免下面的形式:

阅读 ‧ 电子书库

第一个问题是:在将ch与EOF进行第一次比较时,尚未给ch分配值。第二个问题是:如果确实返回了EOF,循环仍将把EOF作为一个合法的字符处理。这些缺点是可以改正的。比如,可以把ch初始化为一个虚设值,并将一个if语句加入到循环中。可是既然已经有了设计范例,为什么还要如此麻烦地修改这个设计呢?这些警告对于其他的输入函数也同样适用,它们也会在遇到文件结尾以后返回一个出错信号(EOF或是NULL指针)。

13.2.5 fclose()函数

fclose(fp)函数关闭由指针fp指定的文件,同时根据需要刷新缓冲区。更正规的程序也许还要检查是否成功关闭了文件。如果文件成功关闭,fclose()函数将返回值0,否则返回EOF。

阅读 ‧ 电子书库

磁盘已满、磁盘被移走或者出现I/O错误等等都会导致fclose()函数执行失败。

13.2.6 标准文件指针

stdio.h文件把3个文件指针与3个C程序自动打开的标准文件进行了关联,如表13.2所示。

表13.2 标准文件及与其相关联的文件指针

 

 

标 准 文 件 文 件 指 针 一般使用的设备
标准输入 stdin 键盘
标准输出 stdout 显示器
标准错误 stderr 显示器

这些指针都是FILE指针类型,所以可以被用作标准I/O函数的参数,就像示例程序中的fp那样。接下来的例子要创建一个新文件,并向其中写入内容。