C程序设计及工程案例分析-第9章文件_第1页
C程序设计及工程案例分析-第9章文件_第2页
C程序设计及工程案例分析-第9章文件_第3页
C程序设计及工程案例分析-第9章文件_第4页
C程序设计及工程案例分析-第9章文件_第5页
已阅读5页,还剩54页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第9章

文件C程序设计及工程案例分析XX大学:XX学习目标理解文件的概念和用途;掌握C语言程序中标准文件操作函数;掌握文本文件和二进制文件的访问方法,掌握随机读写文件的方法;掌握文件的随机读写方法。在C语言中,按文件格式可分为二进制文件与(

)。头文件输出文件输入文件文本文件ABCD提交单选题10分目录9.1文件概述9.2文件的打开与关闭9.3文本文件的访问9.4二进制文件的访问9.5综合应用实例文件概述9.19.1.1基本概念C语言将文件看作是一个字节(字符)的序列,即按一个一个字节(字符)的数据顺序组成。根据数据的组成形式,可分为ASCII文件和二进制文件。ASCII文件又称文本文件,它的每一个字节可放一个ASCII码,代表一个字符,此时文件就是一个文本流。二进制文件是把内存中的数据按其在内存中的存储形式按原样输出到磁盘上存放,此时文件就是一个字节流或二进制流。9.1.1基本概念为了避免频繁的读写磁盘,C语言程序处理文件时自动在内存中为每一个正在使用的文件开辟一块存储空间作为读写文件的缓冲区。当要从磁盘文件中读入数据时,先读一批数据存放到缓冲区中,然后再从缓冲区中读出数据送到程序数据区;当要将程序数据区中数据写入磁盘文件时,先将程序数据区中一部分数据送到缓冲区,可以当缓冲区装满后再一起写入到磁盘文件。9.1.2文件类型指针每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息(如文件的名字、文件状态及文件当前位置等)。这些信息是保存在一个结构体变量中的。该结构体类型在头文件“stdio.h”中声明,名称为“FILE”。文件操作时,通常使用一个指向FILE类型变量的指针变量,而不是直接使用FILE类型变量。例如:FILE*fp1,*fp2;定义fp1和fp2为指向FILE类型数据的指针变量,可以使fp1或fp2指向某一个文件的文件信息区(结构体变量),通过该文件信息区中的信息就能够访问该文件。文件的打开与关闭9.29.2.1文件的打开C语言程序访问文件一般有三个步骤:打开文件、读或写文件、关闭文件。打开文件就是将内部文件指针变量关联到一个特定的外部文件名称上的过程。调用标准库函数fopen()打开文件,该函数返回特定外部文件的文件类型指针。fopen()函数在头文件stdio.h中定义,它的一般使用形式为:FILE*fp=NULL;fp=fopen(文件名,打开文件方式);其中,“文件名”是被打开文件的名称,是一个字符串;“打开文件方式”也是一个字符串,指明以何种方式打开文件,打开文件方式见表9.1。函数返回值为指向该文件的文件类型指针。9.2.1文件的打开打开文件方式含

义如果文件不存在"r"打开一个文本文件,在文件头开始读数据。出错"w"打开一个文本文件,如果文件存在,则先删除文件原有内容,然后开始写数据。新建一个文本文件"a"为了向文件末尾增加数据,打开一个文本文件。新建一个文本文件"rb"打开一个二进制文件,在文件头开始读数据。出错"wb"打开一个二进制文件。如果文件存在,则先删除文件原有内容,然后开始写数据。新建一个二进制文件"ab"为了向文件末尾增加数据,打开一个二进制文件。新建一个二进制文件"r+"打开一个文本文件,在文件头开始读或写数据。出错"w+"打开一个文本文件,如果文件存在,则先删除文件中原有内容,然后开始读或写数据。新建一个文本文件"a+"为了读和写数据,打开一个文本文件,在文件末尾处写数据,在文件头开始读数据。新建一个文本文件"rb+"或"r+b"打开一个二进制文件,在文件头开始读或写数据。出错"wb+"或"w+b"打开一个二进制文件,如果文件存在,则先删除文件中原有内容,然后开始读或写数据。新建一个二进制文件"ab+"或"a+b"打开一个二进制文件,在文件末尾处追加数据,在文件头开始读数据。新建一个二进制文件表9.1打开文件方式如果二进制文件a.dat已经存在,现在要求打开该文件进行读、写数据,应以(

)方式打开。"r""rb""rb+""rwb"ABCD提交单选题10分若以“a+”方式打开一个已存在的文件,则以下叙述正确的是()。文件打开时,原有文件内容不被删除,位置指针移到文件末尾,可作添加和读操作文件打开时,原有文件内容不被删除,位置指针移到文件开头,可作重写和读操作文件打开时,原有文件内容被删除,只可作写操作以上各种说法都不正确ABCD提交单选题10分9.2.1文件的打开对于函数fopen,需要说明如下几点:①用“r”方式打开文件(包括“rb”、“r+”、“rb+”),只能用于“读”,即磁盘文件输入到内存中。试图打开一个不存在的文件会出错。②用“w”方式打开文件(包括“wb”、“w+”、“wb+”),只能用于“写”,即内存数据输出到磁盘文件中。如果文件不存在,则在打开时新建一个以指定名字命名的文件,否则先删除原文件中所有数据后才开始写操作。③凡带“+”号的打开方式,打开的文件总是既能“读”,又能“写”。9.2.1文件的打开④当打开文件方式中有“r”时,如果打开文件失败(例如,文件不存在或损坏),则函数fopen将返回一个空指针NULL。所以安全的做法是用下面的语句形式打开一个文件。if((fp=fopen(文件名,"r"))==NULL){printf("Openfilefailed。\n");exit(0);/*需要包含头文件:stdlib.h*/}⑤当需要新建文件时,如果指定的文件夹不存在,函数fopen不会创建文件夹,而是失败,返回一个空指针NULL。例如,如果E盘根目录(文件夹)下不存在名为“abc”的子文件夹,则执行下列语句后不会新建文件,fp的值为NULL。fp=fopen("E:\\abc\\a.dat","wb");若执行fopen函数时发生错误,则函数的返回值是(

)。一个随机地址值1NULLEOFABCD提交单选题10分9.2.1文件的打开⑥Windows系统中,从文本文件读入字符时,遇到回车换行符,系统会把它们换成一个换行符'\n',而在写文本文件时会把换行符'\n'换成回车符(ASCII码为13)和换行符两个符号。⑦程序中可以使用3个标准的文本流:标准输入流(stdin)、标准输出流(stdout)、标准出错输出流(stderr)。系统已对这3个文件指定了与终端的对应关系。使用这3个流文件时,不需要使用函数fopen打开它们,直接通过stdin、stdout、stderr这三个文件指针变量操作即可。例如,若有char型变量c,通常可以用c=fgetc(stdin)代替scanf("%c",&c)。以读方式打开一个已有的文本文件“file1”,以下fopen()函数正确的调用方式是(

)。fp=fopen("file1","r");fp=fopen("file1","wb");fp=fopen("file1","rb");fp=fopen("file1","w");ABCD提交单选题10分9.2.2文件的关闭为了保证写入到文件缓冲区中的数据一定写到磁盘文件中,如果不再需要使用该文件时应及时执行关闭文件的操作,以避免文件数据的丢失或被误用。关闭文件包括:将文件缓冲区中未写入到文件的数据写入文件,撤销文件信息区和文件缓冲区,使文件指针变量不再指向该文件。关闭文件使用函数fclose,它的一般使用形式为:fclose(文件指针变量);例如,fclose(fp);函数fclose有int型的返回值,若成功关闭文件,返回值为0,若检测出任何出错则返回值为EOF(-1)。文本文件的访问9.39.3.1字符输入/输出函数对文本文件输入或输出字符的函数如下表所示。向文件写一个字符或从文件读一个字符,文件的读写位置后移一个字符。函数原型说

明intfputc(intc,FILE*fp)把字符c(转换为unsignedchar类型)输出到流fp中。返回写入的字符,错误则返回EOF。intputc(intc,FILE*fp)除是以宏实现的外,等价于函数fputc。intfgetc(FILE*fp)返回fp流的下一个字符,返回类型为unsignedchar(被转换为int类型)。如果到达文件末尾或发生错误,则返回EOF。intgetc(FILE*fp)除是以宏实现的外,等价于函数fgetc。#include<stdio.h>#include<stdlib.h>intmain(void){FILE*fp;charc='A';inti;if((fp=fopen("a.txt","w"))==NULL){ printf("Createfilefailed.\n"); exit(0);}程序9.1将26个大写字母按顺序写入到一个文本文件中,每行13个。for(i=0;i<26;i++){ fputc(c+i,fp); if(i==13-1)fputc('\n',fp);}fclose(fp);return0;}#include<stdio.h>#include<stdlib.h>intmain(void){FILE*fp1,*fp2;charc;if((fp1=fopen("a.txt","r"))==NULL){ printf("Openfilefailed.\n"); exit(0);}if((fp2=fopen("b.txt","w"))==NULL){ printf("Createfilefailed.\n"); exit(0);}if((fp2=fopen("b.txt","w"))==NULL){ printf("Createfilefailed.\n"); exit(0);}程序9.2复制文本文件a.txt,生成文件b.txt。c=fgetc(fp1);while(!feof(fp1)){ fputc(c,fp2); c=fgetc(fp1);}fclose(fp1);

fclose(fp2);

return0;}注意:feof函数只有在尝试读取文件结束符之后才会返回非零值。也就是说,当文件指针指向文件的最后一个字节时,feof函数仍然会返回0,只有在尝试读取该字节之后,feof函数才会返回非零值。fputc(ch,fp)把一个字符ch写到fp所指示的磁盘文件中,若写文件失败则函数的返回值为(

)。01EOF非0ABCD提交单选题10分9.3.2字符串输入/输出函数对文本文件输入或输出字符串的函数如下表所示。向文件写一个字符串或从文件读一个字符串,文件的读写位置后移到该字符串后的下一个字符处。函数原型说

明intfputs(constchar*s,FILE*fp)把字符串s(不包含字符'\0')输出到流fp中。若出现写错误,返回EOF,否则返回一个非负值。char*fgets(char*s,intn,FILE*fp)最多将n-1个字符(含换行符)读入到数组s中,且以符号'\0'结尾。当遇到换行符或文件结尾时,读取过程终止。返回值为s,如果遇到文件尾且未读入字符到数组s中,则数组s内容保持不变并返回NULL,如果发生错误,则数组s内容不确定并返回NULL。#include<stdio.h>#include<stdlib.h>intmain(void){FILE*fp;chars[41];/*最多存放40个有效字符*/if((fp=fopen("file3.txt","w"))==NULL){ printf("Createfilefailed.\n"); exit(0);}gets(s);程序9.3从键盘输入一段文字(每行不超过40个字符),将其保存到文件file3.txt中,遇到行首字符为'#'表示结束('#'不写入到文件中)。

while(s[0]!='#'){ fputs(s,fp); fputc('\n',fp); gets(s);}

fclose(fp);

return0;}#include<stdio.h>#include<stdlib.h>intmain(void){

FILE*fp;chars[42];if((fp=fopen("file3.txt","r"))==NULL){ printf("Openfilefailed.\n"); exit(0);}

程序9.4将上例所得文本文件file3.txt的内容输出到屏幕上。/*每行不超过40个字符,所以换行符会存放到s中*/fgets(s,41,fp);

while(!feof(fp)){ printf("%s",s); fgets(s,41,fp);}

fclose(fp);

return0;}9.3.3格式化方式输入/输出函数函数fprintf实现向文件中写数据,函数fscanf实现从文件中读数据。如果把函数fprintf的第一个参数改为“stdout”,则其功能与函数printf相同,如果把函数fscanf的第一个参数改为“stdin”,则其功能与函数scanf相同。它们的调用形式为:如果操作成功,函数fscanf返回输入的数据项数,否则返回0,如果读到文件尾,返回EOF(-1)。如果操作成功,函数fprintf返回实际写入的字符数,否则返回一个负值。intfprintf(FILE*fp,格式串,输出项列表);

intfscanf(FILE*fp,格式串,输入项列表);程序9.5假定学生的成绩信息包括学号、姓名、课程名、分数,创建一个名为score.txt的文本文件,从键盘输入成绩数据,并写入到文件score.txt中,当输入的学号为0时结束程序。#include<stdio.h>#include<stdlib.h>structcj{ intsno; charsname[10]; charcname[10]; intscore;};intmain(void){FILE*fp;structcjs;intsno;if((fp=fopen("score.txt","w"))==NULL){ printf("Createfilefailed.\n"); exit(0);}程序9.5假定学生的成绩信息包括学号、姓名、课程名、分数,创建一个名为score.txt的文本文件,从键盘输入成绩数据,并写入到文件score.txt中,当输入的学号为0时结束程序。printf("Inputsno:");scanf("%d",&sno);while(sno!=0){ printf("Inputsnamecnamescore:\n"); scanf("%s%s%d",s.sname,ame,&s.score); fprintf(fp,"%d%s%s%d\n",sno,s.sname,ame,s.score); printf("Inputsno:"); scanf("%d",&sno);}fclose(fp);return0;}程序9.6将程序9.5生成的文件score.txt中数据显示在屏幕上。#include<stdio.h>#include<stdlib.h>structcj{ intsno; charsname[10]; charcname[10]; intscore;};intmain(void){FILE*fp;structcjs;if((fp=fopen("score.txt","r"))==NULL){ printf("Openfilefailed.\n"); exit(0);}fscanf(fp,"%d%s%s%d",&s.sno,s.sname,ame,&s.score);while(!feof(fp)){printf("%d%s%s%d\n",s.sno,s.sname,ame,s.score);

fscanf(fp,"%d%s%s%d",&s.sno,s.sname,ame,&s.score);}fclose(fp);return0;}从fp所指向的文件中读取两个整数并分别赋给两个整型变量a和b,正确的形式是(

)。fscanf(“%d%d”,&a,&b,fp);fscanf(fp,“%d%d”,&a,&b);fscanf(“%d%d”,a,b,fp);fscanf(fp,“%d%d”,a,b);ABCD提交单选题10分二进制文件的访问9.49.4.1数据块输入/输出函数数据块输出函数fwrite和输入函数fread是二进制形式输入输出函数。在输入输出数据时不必进行二进制数据与ASCII码之间的转换,读写数据速度相对较快。它们的调用形式为:unsignedfwrite(数据类型*buffer,unsignedsize,unsignedcount,FILE*fp)unsignedfread(数据类型*buffer,unsignedsize,unsignedcount,FILE*fp)buffer:是一个指针变量。对fread来说,它是用来存放从文件读入的数据在存储区的首地址。对fwrite来说,是要把此地址开始的存储区中的数据输出到文件。size:一次读写的字节数。count:要读写多少次(每次读取的数据量为size字节)。fp:代表文件的FILE类型指针变量。返回值:正常情况下,返回函数第三个参数count值,否则返回0。程序9.7假定学生的成绩信息包括学号、姓名、课程名、分数,创建一个名为score.dat的二进制文件,从键盘输入成绩数据,并写入到文件score.dat中,当输入的学号为0时结束程序。#include<stdio.h>#include<stdlib.h>structcj{ intsno; charsname[10]; charcname[10]; intscore;};intmain(void){FILE*fp;structcjs;intsno;if((fp=fopen("score.dat","wb"))==NULL){ printf("Createfilefailed.\n"); exit(0);}printf("Inputsno:");程序9.7假定学生的成绩信息包括学号、姓名、课程名、分数,创建一个名为score.dat的二进制文件,从键盘输入成绩数据,并写入到文件score.dat中,当输入的学号为0时结束程序。scanf("%d",&sno);while(sno!=0){ printf("Inputsnamecnamescore:\n");

scanf("%s%s%d",s.sname,ame,&s.score);

s.sno=sno;

fwrite(&s,sizeof(s),1,fp);

printf("Inputsno:");

scanf("%d",&sno);}fclose(fp);return0;}已知有定义,FILE*fp;charstr[]="Good!";fp=fopen("filename.dat","wb");将数组str中存放的字符串写到名为filename.dat的二进制文件中,需要的语句是(

)。fwrite(str[0],sizeof(char),1,fp);fread(str,sizeof(char),5,fp);fwrite(fp,sizeof(char),5,str);fwrite(str,sizeof(char),5,fp);ABCD提交单选题10分程序9.8将程序9.7生成的二进制文件score.dat中数据显示在屏幕上。#include<stdio.h>#include<stdlib.h>structcj{ intsno; charsname[10]; charcname[10]; intscore;};intmain(void){FILE*fp;structcjs;intsno;if((fp=fopen("score.dat","rb"))==NULL){ printf(“Openfilefailed.\n"); exit(0);}程序9.8将程序9.7生成的二进制文件score.dat中数据显示在屏幕上。

fread(&s,sizeof(s),1,fp);while(!feof(fp)){ printf("%d%s%s%d\n",s.sno,s.sname,ame,s.score); fread(&s,sizeof(s),1,fp);}fclose(fp);return0;}FILE*fp;intx=32;fp=fopen("my.txt","wb");fwrite(&x,4,1,fp);fclose(fp);下面说法正确的是(

)my.txt保存的文件为文本文件,能够直接打开查看,文件内容为32。fwrite是写文件,因此不用加&。my.txt虽然是文件文件,但内容是以二进制形式存储,不能直接打开查看。fwrite是用于二进制的写操作,因为存储为txt文本文件,因此会转换成文本"32",作为文本文件存储。ABCD提交单选题10分9.4.2随机访问这里我们只讨论简单而有用的二进制文件的随机访问。文件打开后就可以进行读写,不妨把“接下来要读写的下一个字节的位置”称之为文件当前读写位置。打开文件时,如果打开方式串中不含“a”,文件当前读写位置都在文件头。常用于控制文件当前读写位置的函数:rewind、fseek和ftell。(1)函数rewind一般使用形式:voidrewind(FILE*fp)函数功能:使文件当前读写位置移动到文件开头位置。返回值:无。9.4.2随机访问常用于控制文件当前读写位置的函数:rewind、fseek和ftell。(2)函数fseek一般使用形式:intfseek(FILE*fp,longintoffset,intwhence)函数功能:设置文件当前读写位置,后续的读写操作将从新位置开始。此位置被设置为从whence开始的第offset个字节处。whence的值可能为SEEK_SET(0)、SEEK_CUR(1)或SEEK_END(2),分别代表:文件开头、当前读写位置、文件末尾。返回值:仅当请求不能被满足时才返回非0值,设置成功则返回0。(3)函数ftell一般使用形式:longintftell(FILE*fp)函数功能:获得文件当前读写位置。返回值:如果成功,返回值为位移量,否则返回-1。程序9.9输出文件长度(字节数)。从键盘输入文件名(可含路径,不超过30个字符)。#include<stdio.h>#include<stdlib.h>intmain(void){FILE*fp;charfilename[31];printf("Inputfilename:\n");scanf("%30s",filename);/*输入路径时注意\\*/if((fp=fopen(filename,"rb"))==NULL){ printf("Openfilefailed.\n"); exit(0);}

fseek(fp,0,SEEK_END);

printf("Lengthis%ldBytes\n",ftell(fp));fclose(fp);return0;}程序9.10编程实现复制文件操作。#include<stdio.h>#include<stdlib.h>intmain(void){FILE*fp1,*fp2;charfilename[31],newfilename[31],c;inti;longn;printf("Inputfilename:\n");scanf("%31s",filename);if((fp1=fopen(filename,"rb"))==NULL){

printf("Openfilefailed.\n");

exit(0);}程序9.10编程实现复制文件操作。printf("Inputnewfilename:\n");scanf("%31s",newfilename);if((fp2=fopen(newfilename,"wb"))==NULL){ printf("Createfilefailed.\n"); exit(0);}fseek(fp1,0,SEEK_END);n=ftell(fp1);rewind(fp1); for(i=0;i<n;i++){/*此时,n为文件字节数*/ fread(&c,1,1,fp1); fwrite(&c,1,1,fp2);}

fclose(fp2);fclose(fp1);return0;}程序9.11假定已利用程序9.7创建了一个包含5条记录的成绩信息文件,名称为score.dat。编程实现:将倒数第3条成绩记录中的分数增加5分。#include<stdio.h>#include<stdlib.h>structcj{ intsno; charsname[10]; charcname[10]; intscore;};intmain(void){FILE*fp;structcjs;if((fp=fopen("score.dat","rb+"))==NULL){ printf("Openfilefailed.\n"); exit(0);}程序9.11假定已利用程序9.7创建了一个包含5条记录的成绩信息文件,名称为score.dat。编程实现:将倒数第3条成绩记录中的分数增加5分。fseek(fp,-3*(long)sizeof(s),SEEK_END);fread(&s,sizeof(s),1,fp);s.score+=5;fseek(fp,-1*(long)sizeof(s),SEEK_CUR);/*读数据后要回退到原来位置*/fwrite(&s,sizeof(s),1,fp); fclose(fp);return0;}若一个文件指针变量fp所指向的文本文件有1000个字符,当前文件位置指针指向第300个字符,那么执行fseek(fp,-100L,SEEK_CUR);以后,文件位置指针指向第(

)个字符。100200400900ABCD提交单选题10分综合应用实例——个人消费记账本9.5程序9.12个人消费记账本#include<stdio.h>#include<stdlib.h>#defineN2

/*初始容量*/#defineINC100/*单次容量增量*/typedefstructrec{intyear;intmonth;intday;/*年、月、日*/floatcost;

/*金额*/charmemo[30];/*备注*/}record;record*rec;intlength,capacity;程序9.12个人消费记账本voidInitialize(){/*初始化:从文件中读取数据存放到rec中。*/FILE*fp;recordx;rec=(record*)malloc(N*sizeof(record));if(rec==NULL)exit(0);length=0;capacity=N;if((fp=fopen("data.dat","rb"))!=NULL){fread(&x,sizeof(record),1,fp);while(!feof(fp)){if(length==capacity){rec=(record*)realloc(rec,(capacity+INC)*sizeof(record));capacity+=INC;}rec[length++]=x;fread(&x,sizeof(record),1,fp);}fclose(fp);}}程序9.12个人消费记账本voidSaveFile(){

/*保存到文件data.dat*/

FILE*fp;if((fp=fopen("data.dat","wb"))==NULL){printf("Failtoopenfile!\n");exit(0);

}intn=fwrite(rec,sizeof(record),length,fp);if(n<length){printf("Failtowritefile!\n");fclose(fp);exit(0);}fclose(fp);printf("Savesuccessfully.\n");}程序9.12个人消费记账本voidAddRec(){

/*添加消费记录*/

recordr;printf("请输入年月日,格式:yyyy-mm-dd\n");scanf("%d-%d-%d",&r.year,&r.month,&r.day);printf("请输入消费的金额(可以有小数)\n");

scanf("%f",&r.cost);printf("请输入该消费的备注(不含空格)\n");

scanf("%s",r.memo);if(length==capacity){rec=(record*)realloc(rec,(capacity+INC)*sizeof(record));capacity+=INC;}rec[length++]=r;}程序9.12个人消费记账本voidPrintDate(inty,intm,intd){

/*输出年、月、日*/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论