//程序清单13.1 count.c程序
/* count.c -- 使用标准 I/O */
#include <stdio.h>
#include <stdlib.h> // 提供 exit()的原型
int main(int argc, char *argv[])
{
int ch;// 读取文件时,储存每个字符的地方
FILE *fp;// “文件指针”
unsigned long count = 0;
if(argc != 2)
{
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
printf("Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF)
{
putc(ch, stdout);// 与 putchar(ch); 相同
count++;
}
fclose(fp);
printf("File %s has %lu characters\n", argv[1], count);
return 0;
}
fopen()
该程序使用fopen()函数打开文件。
该函数声明 在stdio.h中。
它的第1个参数是待打开文件的名称,更确切地说是一个包含改文件名的字符串地址。
第2个参数是一个字符串,指定待打开文件的模式。
表13.1列出了C库提供的一些模式。
新的C11新增了带x字母的写模式,与以前的写模式相比具有更多特性。
第一,如果以传统的一种写模式打开一个现有文件,fopen()会把该文件的长度截为 0,这样就丢失了该文件的内容。
但是使用带 x字母的写模式, 即使fopen()操作失败,原文件的内容也不会被删除。
第二,如果环境允许, x模式的独占特性使得其他程序或线程无法访问正在被打开的文件。
警告
如果使用任何一种"w"模式(不带x字母)打开一个现有文件,该文件的内容会被删除,以便程序在一个空白文件中开始操作。
然而,如果使用带x字母的任何一种模式,将无法打开一个现有文件。
程序成功打开文件后,fopen()将返回文件指针(file pointer),其他I/O函数可以使用这个指针指定该文件。
文件指针(该例中是fp)的类型是指向 FILE的指针,FILE是一个定义在stdio.h中的派生类型。
文件指针fp并不指向实际的文件,它指向一个包含文件信息的数据对象,其中包含操作文件的 I/O函数所用的缓冲区信息。
因为标准库中的I/O函数使用缓冲区,所以它们不仅要知道缓冲区的位置,还要知道缓冲区被填充的程度以及操作哪一个文件。
标准I/O函数根据这些信息在必要时决定再次填充或清空缓冲区。
fp指向的数据对象包含了这些信息(该数据对象是一个 C结构,将在第14章中介绍)。
getc()/putc()
getc()和putc()函数与getchar()和putchar()函数类似。
所不同的是,要告诉 getc()和putc()函数使用哪一个文件。
下面这条语句的意思是“从标准输入中获取一个字符”:
ch = getchar();
然而,下面这条语句的意思是“从fp指定的文件中获取一个字符”:
ch = getc(fp);
与此类似,下面语句的意思是“把字符ch放入FILE指针fpout指定的文件中”:
putc(ch, fpout);
在putc()函数的参数列表中,第1个参数是待写入的字符,第2个参数是文件指针。
程序清单13.1把stdout作为putc()的第2个参数。stdout作为与标准输出相关联的文件指针,定义在stdio.h中,所以putc(ch, stdout)与putchar(ch)的作用相同。
实际上,putchar()函数一般通过putc()来定义。
与此类似,getchar()也 通过使用标准输入的getc()来定义。
fclose()
fclose(fp)函数关闭fp指定的文件,必要时刷新缓冲区。
对于较正式的程序,应该检查是否成功关闭文件。
如果成功关闭,fclose()函数返回0,否则返回EOF:
if (fclose(fp) != 0)
printf("Error in closing file %s\n", argv[1]);
如果磁盘已满、移动硬盘被移除或出现I/O错误,都会导致调用fclose() 函数失败。