文件是一种信息存储的方式,程序设计不可避免要进行各种文件操作,一个程序在运行过程中通常要从文件中读取信息,在文件中存储计算结果。
1 C文件的概念
在C语言中实现文件操作一般采取两种途径。
第一种:调用C语言中有关文件处理的标准库函数。
第二种:直接调用操作系统提供的有关方面的功能。
所谓"文件"一般指存储在外部介质上数据的集合。
2 文件类型指针
Turbo C在stdio.h文件中有以下的文件类型声明:
typedef struct
{ short level; /*缓冲区"满"或"空"的程度*/
unsigned flags; /*文件状态标志*/
char fd; /*文件描述符*/
unsigned char hold; /*如无缓冲区不读取字符*/
short bsize; /*级冲区的大小*/
unsigned char *baffer; /*数据缓冲区的位置*/
unsigned ar *curp; /*指针,当前的指向*/
unsigned istemp; /*临时文件,指示器*/
short token; /*用于有效性检查*/
}FILE;
3 文件的打开和关闭
和其他高级语言一样,对文件读写之前应该"打开"该文件,在使用结束之后应关闭该文件。
一、文件的打开(fopen函数)
ANSI C规定了标准输入输出函数库,用fopen()函数来实现打开文件。fopen函数的调用方式通常为:
FILE *fp;
fp=fopen(文件名,使用文件方式);
例如:fp=fopen("al",nr");
它表示要打开名字为al的文件,使用文件方式为"读入"(r代表read,即读入),fopen函数带回指向al文件的指针并赋给fp,这样fp就和文件al相联系了,或者说,fp指向al文件。可以看出,在打开一个文件时,通知给编译系统以下3个信息:①需要打开的文件名,也就是准备访问的文件的名字。②使用文件的方式("读"还是"写"等)。③让哪一个指针变量指向被打开的文件。
说明:
(1)用"r"方式打开的文件只能用于向计算机输人而不能用作向该文件输出数据,而且该文件应该已经存在,不能用"r"方式打开一个并不存在的文件(即输入文件),否则出错。
(2)用"w"方式打开的文件只能用于向该文件写数据(即输出文件),而不能用来向计算机输入。如果原来不存在该文件,则在打开时新建立一个以指定的名字命名的文件。如果原来已存在一个以该文件名命名的文件,则在打开时将该文件删去,然后重新建立一个新文件。
(3)如果希望向文件末尾添加新的数据(不希望删除原有数据),则应该用"a"方式打开。但此时该文件必须已存在,否则将得到出错信息。打开时,位置指针移到文件末尾。
(4)用"r+"、"w+"、"a+"方式打开的文件既可以用来输人数据,也可以用来输出数据。用"r+"方式时该文件应该已经存在,以便能向计算机输入数据。用"w+"方式则新建立一个文件,先向此文件写数据,然后可以读此文件中的数据。用"a+"方式打开的文件,原来的文件不被删去,位置指针移到文件末尾,可以添加,也可以读。
(5)如果不能实现"打开"的任务,fopen函数将会带回一个出错信息。出错的原因可能是用"r"方式打开一个并不存在的文件;磁盘出故障;磁盘己满无法建立新文件等。此时fopen函数将带回一个空指针值NULL(NULL在stdio.h文件中已被定义为0)。
(6)用以上方式可以打开文本文件或二进制文件,这是ANSI C的规定,用同一种缓冲文件系统来处理文本文件和二进制文件。但目前使用的有些C编译系统可能不完全提供所有这些功能(例如有的只能用"r"、"w"、"a"方式),有的C版本不用"r+"、"w+"、"a+",而用"rw"、"wr"、"ar"等,请读者注意所用系统的规定。
(7)在向计算机输人文本文件时,将回车换行符转换为一个换行符,在输出时把换行符转换成为回车和换行两个字符。在用二进制文件时,不进行这种转换,在内存中的数据形式与输出到外部文件中的数据形式完全一致,一一对应。
(8)在程序开始运行时,系统自动打开3个标准文件:标准输入、标准输出、标准出错输出。
二、文件的关闭(fclose 函数)
fclose(文件指针);
例如:fclose(fp);
4 文件的读写
一、fputc函数和fgetc函数(putc函数和getc函数)
1. fputc函数
把一个字符写到磁盘文件上去。其一般调用形式为:
fputc(ch,fp);
2. fgetc函数
从指定的文件读入一个字符,该文件必须是以读或读写方式打开的。fgetc函数的调用形式为:
ch=fgetc(fp);
如果想从一个磁盘文件顺序读入字符并在屏幕上显示出来,可以:
ch=fgetc(fp);
while(ch!=EOF)
{ putchar(ch);
ch=fgetc(fp);
}
如果想顺序读入一个二进制文件中的数据,可以用:
while(! feof(fp))
{c=fgetc(fp);
}
3. fputc和fgetc函数使用举例
例11.1 从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个"#"为止。
#include <stdio.h>
main()
{ file*fp;
char ch,filename[l0];
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL)
{printf("cannot open file\n");
exit(0);
ch=getchar();
while(ch!='#')
{
fputc(ch,fp);putchar(ch);
ch=getchar();
}
fclose(fp);
}
运行情况如下:
file1.c (输入磁盘文件名)
computer and c# (输入一个字符串)
computer and c (输出一个字符串)
可以用DOS命令将file1.c文件中的内容打印出来;
C>type file.c
computer and c
证明了在file1.c 文件中已存入了"computer and c"的信息。
二、fread函数和fwrite函数
ANSI C标准提出设置两个函数(fread和fwrite),用来读写一个数据块。它们的一般调用形式为:
fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
其中:
buffer:是一个指针。对fread来说,它是读入数据的存放地址。对fwrite比来说,是要输出数据的地址(以上指的是起始地址)。
size:要读写的字节数。
count:要进行读写多少个size字节的数据项。
fp:文件型指针。
如果文件以二进制形式打开,用fread和fwrite函数就可以读写任何类型的信息,如:
fread(f,4,2,fp);
其中f是一个实型数组名。一个实型变量占4个字节。这个函数从fp所指向的文件读入2次(每次4个字节)数据,存储到数组f中。
如果有一个如下的结构体类型:
struct student_type
{char name[10];
int num;
int age;
char addr[30];
}stud[40];
结构体数组stud有40个元素,每一个元素用来存放一个学生的数据(包括姓名、学号、年龄、地址)。假设学生的数据已存放在磁盘文件中,可以用下面的for语句和fread函数读入40个学生的数据:
for(i=0;i<40;i++)
fread(&stud[i],sizeof(struct student_type),l,fp);
同样,以下for语句和fwrite函数可以将内存中的学生数据输出到磁盘文件中去:
for(i=0;i<40,i++)
fwrite(&stud[i],sizeof(struct student_type),l,fp);
如果fread或fwrite调用成功,则函数返回值为count的值,即输人或输出数据项的完整个数。
11.4.3 fprintf函数和fscanf函数
它们的一般调用方式为:
fprintf(文件指针,格式字符串,输出表列);
fscanf(文件指针,格式字符串,输入表列);
例如:
fprintf(fp,"%d,%6.2f",i,t);
它的作用是将整型变量i和实型变量t的值按%d和%6.2f的格式输出到fp指向的文件上。