第12章 文件的基本操作
在实际应用中,大量的信息不可能每次都从键盘输入,而一般都是以文件的形式存储在外存上。此外,有时还需要保存计算机的处理结果,需要在外存上做永久性的保存,而不是简单地在显示器上显示。所有这些操作都和文件的处理有关。
因此,本章主要以磁盘文件为主,介绍Turbo C 2.0提供的基本文件操作函数。
12.1 文件操作的引入
现在,有这样一个问题需要解决:有10个人合作写某一软件的说明书,每人各写一部分,而且每部分最终要合在一起以一个文本文件的形式存放在计算机中。需要编写一个程序将这10个文本文件连接在一起,形成一个具有全部内容的文本文件。
对于这一问题,该如何解决呢?
以前,大家已经学习了C语言的基本输入/输出函数,通过C语言的基本输入/输出函数(如scanf()、printf()、getchar()、putchar()、gets()、puts()等)可以很方便地进行信息的输入/输出,从而可以解决一些基本的输入/输出问题。
但对于该问题,以前的解决方法显然不能满足要求。为了解决此类问题,C语言提供了文件操作函数。
12.2 文件的基本概念
所谓“文件”,一般指存储在外部介质上的有组织的数据集合。
数据只有以一种永久性的方式存放起来才能在需要时被方便地访问。在计算机中,数据可以永久性地存储在软盘、硬盘、光盘这样的设备上,此时,操作系统就会在这些设备上为存储的数据分配足够大的空间。存储数据的目的是为了以后能够读取文件内容,所以系统允许用户为所分配的存储区域指定名字(文件名),并将数据写到这些区域中。其实,这些存储在存储介质上的特定区域里的信息的集合就是文件。
以前学习到的输入和输出,都是暂时性的输入与输出,即在应用程序运行时,从键盘输入数据,运行结果在显示器上显示。当应用程序终止时,这些数据将全部消失。但在实际的程序运行中,常常需要将一些数据(运行的最终结果或中间数据)输出到外存上存储起来,以后需要时再从外存输入到计算机内存,所有这些都需要通过磁盘文件来完成。
12.2.1 C语言支持的文件格式
C语言支持的是流式文件,它把文件看做由一个一个的字符(字节)数据组成的序列。根据数据的组织和操作形式,可分为ASCII文件和二进制文件。
1.ASCII文件
ASCII文件又称为文本文件,它是在一个字节的存储单元上存放一个字符(在外存上存放的是该字符的ASCII码,每个字符将占一个字节)。
例如:存储ABC,它将在外存上占3个存储单元,用来存放010000010100001001000011。其中,01000001为A的ASCII码,01000010为B的ASCII码,01000011为C的ASCII码。每个ASCII码占据8位。如图12.1所示。
图12.1 ABC的ASCII文件存放方式
又如:有一个整数257,在内存中占2个字节(0000000100000001),如果按ASCII形式输出,它将在外存上占3个字节,用于存放每一位数字的ASCII码。如图12.2所示。
图12.2 257的ASCII文件存放方式
2.二进制文件
二进制文件是把内存中的数据按其在内存中的存储格式在磁盘上原样保存。
例如:有一个整数257,在内存中占2个字节(0000000100000001),如图12.3所示,所以按二进制格式输出时,在外存上也只占2个字节,如图12.4所示。
图12.3 257在内存中的表现方式 图12.4 257的二进制文件存放方式
对字符而言,由于其外存存储格式和内存表示格式相同,所以,在外存上也存放每个字符的ASCII码,以ABC的存储为例,如图12.5所示。
图12.5 ABC的二进制文件存放方式
3.两种存储格式的区别
用ASCII码格式存储文件,一个字节代表一个字符,便于对字符进行逐个处理,也便于输出字符。但占较多存储空间,而且要花费一些时间进行转换(二进制码与ASCII码间的转换)。
用二进制格式存储文件,可以节省外存空间和转换时间,但字节并不与字符对应,不能直接输出字符形式。
在实际的软件开发中,中间结果数据一般都需要暂时保存在外存上以便以后使用,在这种情况下,常用二进制文件方式进行保存。
注意:① 在C语言中,一个文件是一个字节流或二进制流。它把数据看做是一连串不考虑记录界限的字符(字节)。② 在C语言中,对文件的存取是以字符(字节)为单位的,数据输入/输出的开始和结束仅受程序控制而不受物理符号(如回车换行符)控制,这种文件被称为流式文件。
12.2.2 缓冲文件系统
ANSI C采用缓冲文件系统,它既可用于处理文本文件,又可用于处理二进制文件。
1.缓冲文件系统
所谓“缓冲文件系统”,是指系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区,从内存向磁盘输出数据必须先送到内存中的缓冲区(用户写文件由用户调用相关函数完成),缓冲区被充满后数据才被一并输出到磁盘中(系统写文件由系统自动完成);如果从磁盘向内存读取数据,则一次从磁盘文件将一批数据输入到内存缓冲区,然后从缓冲区逐个地将数据输送到程序数据区(存入程序变量)。缓冲区的大小由各个具体的C语言版本确定,一般为512字节。其工作过程如图12.6所示。
图12.6 缓冲文件系统工作原理
2.标准级文件读/写
在C语言中,没有提供输入/输出语句,所有输入/输出都是通过函数实现的,对文件的读/写也是通过库函数实现的。
对文件处理有两级方法:即标准级和系统级。
所谓标准级,就是这些函数更符合C语言的普通标准,与其他机器上的C语言更兼容,更容易移植到其他机器、操作系统上。对程序员来说,标准级函数更高级,也更容易使用,功能更强。另外,它支持文件缓冲系统,磁盘存取次数较少,效率更高。
在使用标准级函数时,经常把被操作的文件看做是一个字符流。所以标准级函数有时也被称为流式输入/输出函数。
所谓系统级,是指这些函数往往直接调用操作系统,正因为如此,系统级函数速度更快,内存占用更少,但兼容性更差。
对程序员来说,系统级函数使用起来比较困难,对操作系统的依赖性较强,它们功能交叉,没有自动缓冲能力,也没有格式输入/输出的能力,且移植性较差。
标准级函数有时被错误地理解为只提供流式输入/输出,即把文件看做字符流或字符序列。虽然大部分情况下它们是这样被使用的,但这些函数的功能却不只这些。例如,可以通过标准级函数进行格式化的输入/输出,可以对文件进行随机存取,也可以按块或按记录方式对文件进行存取。
12.2.3 文件操作的基本思路
进行文件操作的基本思路如下:
(1)在文件进行读/写之前,首先使用库函数fopen()打开该文件。fopen()的作用是建立文件和操作系统之间的连接,进行必要的通信(实现所谓对文件的按名操作),并返回一个在以后可以用于文件读/写操作的指针。
(2)文件被打开后,就要考虑使用哪种方式进行文件的读/写。其中以库函数fgetc()和fputc()最为简单。fgetc()的作用是从文件读取一个字符,然后将其存放到用户自己定义的变量中;fputc()的作用是将一个字符写到文件中。
(3)当对文件的操作完成后,就要使用库函数fclose()关闭文件。关闭文件操作将释放不再需要的文件指针,并能保证信息被完整地存储。
12.3 文件基本操作
标准级函数有缓冲功能和安全保护功能,易于使用,然而使用它的最大好处还在于它的兼容性。
12.3.1 文件指针
1.FILE结构
标准级函数添加的许多功能都是由于它使用了FILE这个数据结构,每当打开一个文件进行标准输入/输出时,系统就建立了一个FILE结构,并返回一个指向这个结构的指针。对于随后所有的操作,都以这个结构指针(下面称为文件指针,有时也称为文件流指针)为基础进行。
FILE数据结构:
typedef struct
{
short level;
unsigned flags;
char fd;
unsigned char hold;
short bsize;
unsigned char *buffer;
unsigned char *curp;
unsigned istemp;
short token;
}FILE;
FILE结构中的字段fd称为文件柄。因为标准级的输入/输出操作支持缓冲区操作,假设开始时进行标准级的输入,后来转入系统级的输入,等到再次使用标准级输入时,缓冲区中的内容就可能不再和文件中的数据相一致。所以,不应混合使用系统级的文件柄和标准级的文件指针。
2.文件指针的定义
程序员不应直接存取FILE结构中的任何一个数据域,因为它们仅供内部使用。这里列出这个结构只是为了方便读者理解C语言是怎样维护一个文件的。不同的C编译系统可能定义了完全不同的结构,但其结构的名字可能仍然是FILE。
在文件的标准级操作过程中,可以通过文件指针来使用文件。
文件指针变量的定义如下:
FILE *文件指针;
例如:
FILE *fp;
定义fp是一个指向FILE类型结构体的指针变量。可以使fp指向某一文件的结构体变量,从而通过该结构体变量中的文件信息能够访问该文件。也就是说,通过文件指针变量能够找到与它相关的文件。
如果有n个文件,一般应设n个文件指针变量(指向FILE类型结构体的指针变量),使它们分别指向n个文件(确切地说,指向该文件的信息结构体),以实现对文件的访问。
12.3.2 文件的打开与关闭
在使用文件时,应该遵守文件的基本使用规则:先打开,再使用,最后关闭。
在读/写文件之前,应该首先打开该文件,然后再对其进行相应的读/写操作,当所需的操作完成后,关闭该文件。
文件的打开操作为文件的使用做准备,它为将要使用的文件创建相应的数据结构,并和相应的存储空间发生联系。文件的关闭则是将文件的一些相关信息进行保存。
在文件操作完成时,如果没有执行正确的文件关闭操作就可能造成文件相应信息的丢失,导致文件被损坏。因此,在使用文件时应正确地对文件进行打开和关闭操作。
1.文件的打开
ANSI C规定了标准输入/输出函数库,用fopen()函数来实现打开文件。
fopen()函数的一般形式为:
fopen(文件名,使用文件方式);
说明:文件名为将要打开的文件的名字,可以带路径。如果是已经存在的文件,则文件应该为全名,即包括其主文件名和扩展名。使用文件方式用于说明使用者对文件的操作方式。
在书写路径时注意路径分隔符“\”的正确表示“\\”,勿使用双反斜线“//”和反斜线“/”,这是程序员经常犯的一个错误。
例如:
FILE *fp1,*fp2,*fp3;
fp1=fopen("abc", "r");
fp2=fopen ("d:\\mydoc\\stu.dat","r");
fp3=fopen("a1.txt","r");
表示以只读方式打开文件abc、d:\mydoc\stu.dat和文件a1.txt。其中,fp1、fp2、fp3为文件指针。可见,在打开一个文件时通知给编译系统三个信息:需要打开的文件名、文件的使用方式、文件指针。文件的常见使用方式如表12.1所示。
表12.1 文件的常见使用方式
使用方式 |
文件不存在 |
文件已经存在 |
|
“r” |
只读 |
报告出现一个错误 |
打开、只读一个文本文件 |
“w” |
只写 |
建立、打开、只写一个文本文件 |
打开该文本文件,并使文件内容为空,只写 |
“a” |
追加 |
建立和打开一个文本文件,只进行追加 |
打开一个文本文件,只向末尾进行追加 |
“rb” |
只读 |
报告出现一个错误 |
打开、只读一个二进制文件 |
“wb” |
只写 |
建立、打开、只写一个二进制文件 |
打开该二进制文件,并使文件内容为空,只写 |
“ab” |
追加 |
建立和打开一个二进制文件,只进行追加 |
打开一个二进制文件,只向末尾进行追加 |
“r+” |
读/写 |
报告出现一个错误 |
打开、读和写一个文本文件 |
“w+” |
读/写 |
建立、打开一个文本文件,读和写 |
打开一个文本文件,并使文件内容为空,读和写 |
“a+” |
读/写 |
建立、打开一个文本文件、读和追加 |
打开一个文本文件、读和追加 |
“rb+” |
读/写 |
报告出现一个错误 |
打开、读和写一个二进制文件 |
“wb+” |
读/写 |
建立、打开一个二进制文件,读和写 |
打开一个二进制文件,并使文件内容为空,读和写 |
“ab+” |
读/写 |
建立、打开一个二进制文件、读和追加 |
打开一个二进制文件、读和追加 |
说明:
① 用“r”方式打开的文件只能读而不能写,且该文件应该已经存在,不能打开一个并不存在的文件,否则出错。
② 用“w”方式打开的文件只能用于向该文件写数据,而不能从该文件读数据。如果原来不存在该文件,系统会新建立一个以指定名字为文件名的新文件,并打开它。如果文件存在,则在打开时将该文件删去,然后重新建立一个新文件。
③ 如果希望向文件末尾添加新的数据(不删除原有数据),则应该用“a”方式打开。但此时该文件必须已存在,否则将得到出错信息。打开时,文件位置指针移到文件末尾。
④ 用“r+”、“w+”、“a+”方式打开文件时既可以读也可以写。用“r+”方式时,该文件必须已经存在,以便能向计算机输入数据;否则出错。用“w+”方式打开一个文件时,可以向文件中写入数据,也可以从文件中读出数据。用“a+”方式打开的文件不被删去,位置指针移到文件末尾,可以添加也可以读。
⑤ 如果无法打开一个文件,fopen()函数将会带回一个出错信息。出错的原因可能是用“r”方式打开一个并不存在的文件;磁盘出故障;磁盘已满无法建立新文件等。此时fopen()函数将带回一个空指针值NULL(NULL在“stdio.h”文件中已被定义为0)。
常用下面的方法打开一个文件:
if((fp=fopen("file","r"))==NULL)
{
printf("cannot open this file\n");
exit(0);
}
先检查打开是否出错,如果出错就在终端上输出“cannot open this file”。exit函数的作用是关闭所有文件,终止正调用的过程。待程序员检查出错误并修改后再运行。
2.文件的关闭
当一个文件使用结束时,应该关闭它,以防止其被误用而造成文件信息的破坏和文件信息的丢失。从本质上讲,“关闭”就是让文件指针变量不再指向该文件,也就是文件指针变量与文件的联系断开,此后不能再通过该指针对该文件进行读/写操作。除非再次打开,使该指针变量重新指向该文件。C语言中使用fclose()函数关闭文件。
fclose()函数的一般形式为
fclose(文件指针);
例如:
fclose(fp);
该语句的作用是将fopen()函数打开文件时所带回的指针赋给fp,用fclose()函数断开它们之间的联系。
在程序终止之前关闭所有仍在使用的文件是我们应该遵守的基本规则,如果不关闭文件将会造成数据丢失。
因为标准C支持缓冲文件系统,如果数据未充满缓冲区而程序结束运行,系统会自动释放其文件缓冲区,从而导致缓冲区中数据的丢失。用fclose()函数关闭文件,可以很好地解决和避免这个问题,它先把缓冲区中的数据输出到磁盘文件,然后才释放文件指针变量和缓冲区空间。
当然,fclose()函数也带回一个值:当成功地执行了关闭操作,其返回值为0;如果返回值为非0,则表示关闭时有错误发生。
12.3.3 字节级的文件的读/写
所谓“字节级的文件读/写”,是指文件的读/写是以字节为单位的。文件在打开之后,就可以进行信息的读取与保存。常用的读/写函数有:fputc()函数和fgetc()函数。
1.文件位置指针
文件位置指针和文件指针是两个不同的概念。文件位置指针用于表示当前正在读/写的数据在文件中的位置。当一个文件被打开后,文件位置指针总是指向文件的开始,即指向第一个数据。当其指向文件末尾时,表示文件结束。
在进行文件读/写时,总是从文件位置指针处开始进行读/写,当读/写完成之后,文件位置指针会自动后移。
当然,用户也可以通过相应的库函数来移动文件位置指针。
2.fputc()函数
fputc()函数的一般形式为
int fputc(char ch , FILE *fp);
该函数的功能是将字符ch写到fp对应的磁盘文件中。其中ch是需要输出的字符,它可以是一个字符型数据,也可以是一个整数(对应的字符的ASCII码值)。fp为文件指针变量,它是使用fopen()函数后所得到的函数返回值。
fputc()函数也返回一个值:如果输出成功则返回值就是输出的字符;如果输出失败,则返回一个EOF。EOF是在“stdio.h”文件中定义的合法整数。
【例12.1】 从键盘读入字符并存入文件,直到用户输入一个“#”符为止。
分析 由于需要保存的是字符,所以需要创建一个文本文件。从键盘每输入一个字符,便将其写入文件,反复输入,直到输入“#”符为止。所输入的字符就构成新文件的内容。
#include "stdio.h"
main()
{
char filename[20];
FILE *fp;
char ch;
scanf("%s",filename);
if((fp=fopen(filename, "w"))==NULL)
{
printf("can't create the file\n");
exit(0);
}
while((ch=getchar())!='#')
fputc(ch,fp);
fclose(fp);
}
3.fgetc()函数
fgetc()函数的一般形式为
int fgetc(FILE *fp);
该函数的功能是从指定文件读入一个字符,该文件必须是以读或读/写方式打开的。
例如:
ch=fgetc(fp);
其中,fp为文件指针变量,它和要读取的文件相关联。ch为字符变量,fgetc()函数会返回一个字符,赋给ch(ch也可以是整型变量,此时是将fgetc()返回的字符的ASCII码值赋予ch)。如果在执行fgetc()函数读字符时遇到文件结束符,则函数返回一个文件结束标志EOF。
【例12.2】 从一个磁盘文件顺序读入字符并在屏幕上显示出来。
#include "stdio.h"
main()
{
FILE *fp;
char ch;
if((fp=fopen("d:\\my.dat","r"))==NULL)
{
printf("\n this file does not exit\n");
exit(1);
}
while((ch=fgetc(fp))!=EOF)
putchar(ch);
fclose(fp);
}
注意:EOF是不可输出字符,因此不能在屏幕上显示。由于字符的ASCII码不可能出现-1,因此EOF定义为-1是合适的。当读入的字符值等于EOF时,表示读入的已不是正常的字符而是文件结束符,但这只适用于对文本文件的读/写。
12.3.4 文件结束判断函数
在二进制文件中,信息都是以数值方式存在的。EOF的值可能就是所要处理的二进制文件中的信息。这就出现了需要读入有用数据却被处理为“文件结束”的情况。为了解决这个问题,ANSI C提供了一个feof()函数,可以用它来判断文件是否结束。
feof(fp)用于测试fp所指向的文件的当前状态是否为“文件结束”。如果是,函数feof(fp)的值为1(真),否则为0(假)。
如果想以正确的顺序读入一个文件(包括文本文件与二进制文件)中的数据,文件结束判断就应该使用feof()函数。
例12.2的代码可以修改为
#include "stdio.h"
main()
{
FILE *fp;
int ch;
if((fp=fopen("d:\\my.dat","r"))==NULL)
{printf("\n this file does not exit\n");
exit(1);}
while(!feof(fp))
{ch=fgetc(fp);
putchar(ch);}
fclose(fp);
}
在文件的读/写过程中,当文件未结束时,feof(fp)的值为0,循环继续;当文件结束时,feof(fp)的值为1,退出循环。
【例12.3】 编写一个程序,完成文件的复制功能。
#include "stdio.h"
main()
{
char sou_flise[20],targ_file[20];
FILE *d_in, *d_out;
scanf("%s",sou_file);
scanf("%s",targ_file);
if((d_in=fopen(sou_file, "rb"))==NULL))
{
printf("Cannot open the source file \n");
exit(0);
}
if((d_out=fopen(targ_file, "wb"))==NULL)
{
printf("\n Cannot create the targefile \n");
exit(0);
}
while (!feof(d_in))
fputc(fgetc(d_in),d_out);
fclose(d_in);
fclose(d_out);
}
【例12.4】 有两个磁盘文件x和y,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),结果输出到一个新文件z中。
分析 结果要求按字母顺序保存,可以先将两个文件中的内容读到一个字符数组中,然后对字符数组中的内容进行排序,最后将排序结果写入新文件即可。
#include "stdio.h"
void get_inf(FILE,*fp,char str[],int *n) /*读文件*/
{
while(!feof(fp)) str[(*n)++]=fgetc(fp);
}
void sort_inf(char str[],int n) /*对内容进行排序*/
{ int i,j;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(str[i]>str[j])
{t=str[i];str[i]=str[j];str[j]=t;}
}
main()
{
FILE *fp;
int i,j,n,ni;
int len=0; /*存放字符串长度*/
char str[160],t,ch;
if((fp=fopen("x","r"))==NULL)
{
printf("file x cannot be opened\n");
exit(0);
}
get_inf(fp,str,&len)
fclose(fp);
if((fp=fopen("y","r"))==NULL)
{
printf("file y cannot be opened\n");
exit(1);
}
get_inf(fp,str,&len)
fclose(fp);
sort_inf(str,len);
if((fp=fopen("z","w"))==NULL)
{
printf("file z cannot be created\n");
exit(0);
}
for(i=0;i<len;i++)
fputc(str[i],fp);
fclose(fp);
}
12.4 文件基本应用举例
【例12.5】 编写一个程序,从键盘输入10个学生的学号将其存入文件中。
分析 假定一个学号11位,可以认为它由11个数字或字符组成。存放一个学生学号的过程便归结为向文件中写11个字符的过程。
#include "stdio.h"
void write_code(FILE *fp,char code[]) /*向文件中写一个学号*/
{int i=0;
while(code[i]!= ' \0')
fputc(code[i++],fp);
}
main()
{
char code[12];
FILE *fp;
if((fp=fopen("d:\\student.dat","w"))==NULL)
{
printf("\n this file can not be created \n");
exit(1);
}
for(i=0;i<10;)
{
scanf("%s",code);
if(strlen(code)!=11)
{
printf("\n code error,reinput")
continue;
}
write_code(fp,code);
i++;
}
fclose (fp);
}
【例12.6】 在计算机的D盘上存在文本文件data.dat,该文件存放了全校学生的学号,编写程序,统计2001级、2002级、2003级、2004级的学生人数。
分析 文本文件data.dat是一个已经存在的文件,它可用例12.5的方法产生。假定一个学号11位,可以每次从文件中读出11个字节,将其存入一个字符数组中。取出该字符数组的前4个字节,便可得到该学生的年级。定义一个大小为4的整型数组存放各年级的学生数目。
#include "stdio.h"
void get_code(FILE *fp,char code[]) /*从文件中读一个学号*/
{int i=0;
for(i=0;i<11;i++) code[i++]=fgetc(fp);
code[i]='\0'; /*增加结束标志*/
}
main()
{
char code[12],grade[5];
int num[4]={0},i;
FILE *fp;
if((fp=fopen("d:\\data.dat","r"))==NULL)
{
printf("\n this file does not exit \n");
exit(1);
}
while(!feof(fp))
{
get_code(fp,code);
num[strcmp(strncpy(grade,code,4), "2001")]++;
}
fclose(fp);
}
注意:strncpy(grade,code,4)是将code的前4个字符复制到 grade中。strcmp(strncpy (grade,code,4),“2001”)的返回值为两个字符串的差,若第一个字符串为“2002”,则strcmp(“2002”,“2001”)的值为1。
【例12.7】 在计算机的D盘上存在文本文件data.dat,该文件存放了全校学生的学号,编写程序,将2001级、2002级、2003级、2004级学生的学号分别取出存放到D盘根目录下的data2001.dat、data2002.dat、data2003.dat、data2004.dat中。
#include "stdio.h"
void write_code(FILE *fp,char code[]) /*向文件中写一个学号*/
{int i=0;
while(code[i]!='\0')
fputc(code[i++],fp);
}
void get_code(FILE *fp,char code[]) /*从文件中读一个学号*/
{int i=0;
for(i=0;i<11;i++) code[i++]=fgetc(fp);
code[i]= '\0'; /*增加结束标志*/
}
main()
{
char code[12],grade[5];
int i;
FILE *fp,*targ_fp[4];
if((fp=fopen("d:\\data.dat", "r"))==NULL)
{
printf("\n this file does not exit \n");
exit(1);
}
if((targ_fp[0]=fopen("d:\\data2001.dat","w"))==NULL)
{
printf("\n this file can not be created \n");
exit(2);
}
if((targ_fp[1]=fopen("d:\\data2002.dat","w"))==NULL)
{
printf("\n this file can not be created \n");
exit(3);
}
if((targ_fp[2]=fopen("d:\\data2003.dat","w"))==NULL)
{
printf("\n this file can not be created \n");
exit(4);
}
if((targ_fp[3]=fopen("d:\\data2004.dat","w"))==NULL)
{
printf("\n this file can not be created \n");
exit(5);
}
while(!feof(fp))
{
get_code(fp,code);
write_code(targ_fp[strcmp(strcpy(grade,code,4),"2001")],code);
}
for(i=0;i<4;i++) fclose(targ_fp[i]);
fclose(fp);
}
习题
一、选择题
1.以“w”方式打开文本文件“A:\aa.dat”,若该文件已存在,则 。
A.新写入数据被追加到文件末尾
B.文件被清空,从文件头开始存放新写入数据
C.显示出错信息
D.新写入数据被插入到文件首部
2.从磁盘文件读字符的fgetc函数,其函数原型(头)正确的是 。
A.FILE* fgetc(char) B.int fgetc(FILE *,char)
C.int fgetc(FILE *) D.int fgetc(char,FILE *)
3.对于文件操作方式“rb+”,准确的说法是 。
A.可读/写文本文件 B.只读二进制文件
C.只读文本文件 D.可读/写二进制文件
4.数据-324在二进制文件和文本文件中所占的字节数分别是 。
A.2,2 B.2,4 C.4,2 D.4,4
5.为了向文本文件尾部增加数据,打开文件的方式应采用 。
A.“a” B.“r+” C.“w” D.“w+”
6.将一个整数10002存到磁盘上,以ASCII码和二进制格式存储,所占用的字节数分别是 。
A.2和2 B.2和5 C.5和2 D.5和5
7.在文件使用方式中,字符串“rb”表示 。
A.打开一个已存在的二进制文件,只能读取数据
B.打开一个文本文件,只能写入数据
C.打开一个已存在的文本文件,只能读取数据
D.打开一个二进制文件,只能写入数据
二、填空题
1.下面程序把从终端读入的文本(用@作为文本结束标志)输出到一个名为“bi.dat”的新文件中,请填空。
#include "stdio.h"
FILE *fp;
{ char ch;
if( (fp=fopen ( ) )= = NULL)exit(0);
while( (ch=getchar( )) !='@') ;
fclose(fp);
}
2.以下程序的功能是从键盘上输入一个字符串,把该字符串中的小写字母转换为大写字母,输出到文件“test.txt”中,然后从该文件读出字符串并显示,请填空。
#include "stdio.h"
main()
{
FILE *fp;
char str[100]; int i=0;
if((fp=fopen("text.txt", ))==NULL)
{ printf("can't open this file.\n");exit(0);}
printf("input astring:\n");
gest(str);
while (str[i])
{
if(str[i]='a'&&str[i]<='z')
str[i]= ;
fputc(str[i],fp);
i++;
}
fclose(fp);
fp=fopen("test.txt", );
i=0;
while(!feof(fp)) str[i++]=fgetc(fp);
str[i]='\0';
printf("%s\n",str);
fclose(fp);
}
3.使文件内部指针P重新指向文件头的语句是_________。
4.判断文本文件是否结束时所使用的符号常量EOF的值是______。
5.建立一个磁盘文件,文件名和内容由键盘输入。
#include "stdio.h"
main()
{
char ch, fname[20];
_______________;
scanf("%s",fname);
if ((fp=fopen (________,"w",))==NULL)
exit (0);
ch=getchar ();
while (ch!='*')
{
fputc (ch,fp);
putchar (ch);
ch=getchar ();
}
fclose ( ________);
}
输入磁盘文件名:filec.c
输入一个字符串:Program C*
三、程序设计题
1.编写程序,比较两个文件,并显示它们的第一个不相同的行。
2.从键盘输入一个字符串,将其存入文件中。
3.编写程序,对文件内容进行简单加密。加密规则:任意字母用其后面的第2个字母替换。
4.编写程序,对文件内容进行解密。解密规则:任意字母用其前面的第2个字母替换。
5.从两个文本文件中读出全部内容,按字母顺序排序,排序结果存入新文件。
6.把文本文件“x1.dat”复制到文本文件“x2.dat”中,要求仅复制“x1.dat”中的英文字符。