《新编C语言程序设计教程》课件第11章_第1页
《新编C语言程序设计教程》课件第11章_第2页
《新编C语言程序设计教程》课件第11章_第3页
《新编C语言程序设计教程》课件第11章_第4页
《新编C语言程序设计教程》课件第11章_第5页
已阅读5页,还剩63页未读 继续免费阅读

下载本文档

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

文档简介

第11章文件类型11.1文件类型与文件指针11.2文件的打开与关闭11.3文件的读写与建立11.4文件辅助操作11.5程序设计举例11.1文件类型与文件指针1.文本文件和二进制文件C语言文件把数据看作是一连串的字符(字节)。C语言文件是一个字符(字节)的序列,是一字符流或字节流,是一种流式文件。根据数据的组织形式,可分为文本文件和二进制文件。

文本文件又称为ASCII文件,每一个字节中存放一个ASCII代码,代表一个字符。例如,一个整数123,若用ASCII文件存放,占3个字节的存储单元,1、2、3各用一个字节存储。而1、2、3的ASCII码分别为49、50、51,故123用ASCII文件存放时,存放形式为001100010011001000110011。二进制文件是直接用数据的二进制形式存放。例如,对整数123,二进制为0000000001111011,用二进制文件存放,需2个字节,存放形式为0000000001111011。2.缓冲文件系统和非缓冲文件系统

在缓冲文件系统中,系统自动在内存中为每个正在使用的文件开辟一个缓冲区,文件的存取都是通过缓冲区进行的。缓冲区相当于一个中转站,它的大小由具体的C版本规定,一般为512字节。缓冲文件系统原来用于处理文本文件。在非缓冲文件系统中,系统不为所打开的文件自动开辟缓冲区,缓冲区的开辟由程序完成。非缓冲文件系统原来用于处理二进制文件。

ANSIC不再采用非缓冲文件系统,而只采用缓冲文件系统,在处理二进制文件时,也通过缓冲文件系统进行。ANSIC通过扩充缓冲文件系统,使缓冲文件系统既能处理文本文件,又能处理二进制文件。

3.内部文件和外部文件

存放在外部介质上的文件称为外部文件,通过文件名标识。C程序中的文件称为内部文件,用文件指针来描述。程序中要实现对文件的处理,先必须在内部文件与外部文件之间建立联系,打开文件;然后方可对文件进行操作。文件最基本的操作是读写操作;操作完成应当切断内部文件与外部文件之间的联系,关闭文件。对文件进行的所有操作通过C编译系统提供的标准函数完成,这些函数的信息包含在头文件“stdio.h”中。11.1.2文件类型

在缓冲文件系统中,系统为每个被使用的文件都在内存中开辟一个区域,用来存放文件名、文件状态、缓冲区状态及文件当前位置等信息,这些信息保存在一个结构体变量中。文件类型是一个特殊的结构体类型,一般命名为FILE。用户可以直接使用FILE来定义文件类型变量,存放要处理的文件的基本信息。各种C编译系统的FILE定义可以不同,但均包含进行文件处理所需的基本信息。下面是TURBOC中对FILE的定义:typedefstruct{shortlevel;unsignedflags;charfd;unsignedcharhold;shortbsize;unsignedchar*buffer;unsignedchar*curp;unsignedistemp;shorttoken;}FILE;11.1.3文件指针变量

对文件的描述,往往通过指向文件的文件指针变量来进行。文件指针变量定义的形式为:

FILE*文件指针变量;例如:FILE*fp,*fpa[10];定义了文件指针变量fp和文件指针变量数组fpa。文件指针变量fp及文件指针变量数组fpa的每个分量可以指向一个文件的信息。11.2文件的打开与关闭11.2.1文件的打开

文件的打开用fopen()函数完成,调用方式通常为:

fp=fopen(文件名,文件使用方式);

文件使用方式共有12种,用特定字符形成的字符串来描述。

(1)″r″方式,以只读方式打开文本文件。这时从文件中读数据到内存,故要求文件已经存在。用″r″方式打开的文件只能读,不能同时写。

(2)″w″方式,以只写方式打开文本文件。这时将内存中的数据写入到磁盘文件中。若文件不存在,建立新文件;若文件存在,则刷新文件,重新建立。用″w″方式打开的文件只能写,不能同时读。(3)″a″方式,为文本文件的追加方式。用于向已存在的文件尾部追加新的数据,而文件中原来的数据不被破坏。

(4)″r+″、″w+″、″a+″方式,打开的文本文件既能读又能同时写。

″r+″方式:在读的同时可以进行写。读写位置指针在头部,若原来存在此文件,则以覆盖方式写。

″w+″方式:在写的同时可以进行读。由于打开文件时,文件原来的内容被刷新,一般不要在打开文件后立即读文件。

″a+″:在追加的同时可以进行读。读文件时,从文件首部开始;写文件时,在文件尾部追加。(5)″rb″、″wb″、″ab″、″rb+″、″wb+″、″ab+″是使用二进制文件相应的六种方式。打开文件可得到三个信息:①要访问的文件名。②使用文件的方式。③哪一个指针变量用于指向被打开的文件。打开成功,返回文件指针(文件信息区的起始地址);不能打开,返回空指针。

例如:

(1)fp=fopen(″student.dat″,″w″);以只写方式打开当前盘当前目录下的文本文件中的学生数据文件,用户可将数据写入此磁盘文件中。

(2)fp=fopen(″c:\cj\cjc.dat″,student.dat″,″r″);以只读方式打开C盘成绩子目录下C语言成绩文件,用户可将文件中数据读出来。但此文件必须存在,否则会出错。(3)fp=fopen(″PRG″,″ab+″);打开二进制文件PRG,在读的同时也可以写。为确保文件的读写操作,对文件是否已正常打开往往加上if语句进行控制。例如:

if(fp=fopen((″student.dat″,″w″)==NULL) {printf(″不能打开文件!″);

exit(0);

}

说明:

(1)不是所有编译系统均提供以上12种文件使用方式。

(2)用″r″、″rb″方式打开的文件必须已经存在。

(3)用″w″、″wb″方式打开的文件,可以存在也可以不存在。不存在时,则新建文件;存在时,重新建立,原文件内容不被保留。

(4)在读写文本文件时,对回车换行符要进行转换,读时回车换行符转换成换行符,写时回车换行符转换成回车、换行两个字符。对二进制文件,不进行这种转换。(5)程序运行时,系统自动打开标准输入stdin、标准输出stdout、标准出错输出stderr三个标准文件。stdin、stdout、stderr由系统自动定义,可直接使用。

(6)标准设备文件可与普通文件一样操作,但将产生特殊效果。如写到打印机,将在程序中实现打印输出控制。11.2.2文件的关闭

文件在使用完后,应及时关闭。文件的关闭用fclose()函数完成,调用方式为:

fclose(文件指针变量);关闭文件将使文件指针变量与文件名脱钩,即指针变量不再指向该文件。文件关闭后不能再用该指针变量对文件进行操作,该指针变量可再指向其它文件。顺利执行了关闭操作,将返回函数值0。如返回一个非0值,则表示文件关闭出错。11.3文件的读写与建立11.3.1字符级数据的读和写1.字符级数据的读

函数原型:

intfgetc(FILE*fp);功能:从文件指针fp所指向的文件中读取一个字节的代码值(字符),作为函数的返回值。正常情况下为一个字符,读到文件尾或出错时为EOF(-1)。

说明:

(1)读完一字节数据后,文件指针自动后移。

(2)getc和fgetc是等价的宏。

(3)若文件指针为stdin,则fgetc(stdin)功能与getchar()等价。2.字符级数据的写

函数原型:

intfputc(intch,FILE*fp);功能:将ch写入文件指针fp所指向的文件中。写入成功返回字符值,不成功返回值EOF。说明:

(1)写入数据前,文件指针自动后移。

(2)puttc和fputc是等价的宏。

(3)若文件指针为stdout,则fputc(stdout)功能与puttchar()等价。

(4)文件的建立通过写操作完成。11.3.2字级数据的读和写1.字级数据的读

函数原型:

intgetw(FILE*fp);功能:从文件指针fp所指文件中读一个字的数据(整数),并以它作为函数的返回值。说明:非标准C所提供函数。2.字节数据的写

函数原型:

intputw(intw,FILE*fp);功能:写一个字的数据(整数)到文件指针fp所指的文件中,并以它作为函数的返回值。说明:非标准C所提供函数。11.3.3字符串级数据的读和写1.字符串数据的读

函数原型:

char*fgets(char*str,intlen,FILE*fp);

功能:

从文件指针fp所指的文件中读入一个长度为len-1的字符串,送入到str所指内存地址中。返回值为str的首地址,若读到文件尾或出错,则返回值为NULL。

说明:

(1)字符串读入后在最后加结尾符′\0′。

(2)将读到的回车符作为字符存储。这点与gets()函数不同,gets()把读到的回车符转换成结尾符。

(3)字符串数据的读和写亦称“行处理”。2.字符串数据的写函数原型:

intfputs(char*str,FILE*fp);功能:将str指针所指字符串写入到文件指针fp所指文件中。若该函数成功调用,返回函数值0,否则返回函数值非0。11.3.4数据块数据的读和写1.数据块数据的读函数原型:

unsignedfread(void*buffer,unsignedsize,unsignedcount,FILE*fp);功能:从文件指针fp所指的文件中读取count个大小为size字节的数据块到buffer指针所指的内存中。读到的数据可能含有各种不同的类型。若该函数成功调用,返回count的值。

例如:

inta[100];

fread(a,2,100,fp);/*从fp读取100个大小为2字节的数据块(整数)到数组a中*/2.数据块数据的写

函数原型:

unsignedfwrite(void*buffer,unsignedsize,unsignedcount,FILE*fp);

功能:向文件指针fp所指的文件写入由buffer指针所标识的count个大小为size字节的数据块。若该函数成功调用,返回count的值。例如:

inta[100];

……

fwrite(a,2,100,fp);/*将整个数组a写入文件fp中*/11.3.5格式化数据的读和写1.格式化读函数原型:

intfscanf(FILE*fp,格式字串,地址表);功能:按指定格式从文件fp中读取数据至指定地址。例如:

inti,j;

floatf;

fscanf(fp,"%d%d%f", &i,&j,&f);/*从fp中按指定格式读取数据至i、j、f中*/2.格式化写函数原型:

intfprintf(FILE*fp,格式字串,变量表);功能:按指定格式将给定数据写入文件fp中。使用fscanf( )和fprintf( )函数对磁盘文件进行读和写相当方便,但是输入时需将ASCII码转换为二进制,输出时需将二进制转换成ASCII码,费时间,故一般较少采用,而是使用fread( )和fwrite( )函数。11.3.6文件的建立步骤对文件操作前必须打开文件,文件打开后才可进行读写操作,操作完成应关闭文件。文件的建立步骤如下:

(1)以写方式打开文件。

(2)将数据写入文件,多个数据反复写入。

(3)写完数据关闭文件。例11-1

定义一个函数,建立存放26个英文小写字母的文件LF.DAT。voidcreatfile(){charl;

FILE*fp;

if((fp=fopen(″LF.DAT″,″w″))==NULL)/*打开文件*/{printf(″不能打开文件!″);

exit(0);

}for(l=′a′;l<=′z′;l++)/*写入数据*/fputc(l,fp);

fclose(fp);/*关闭文件*/}

例11-2

定义一个函数,建立存放某班50个同学姓名、C语言成绩的数据文件CCJ.DAT,原始数据由数组参数传入。voidcreatfile(floatx[]){inti;

FILE*fp;

if((fp=fopen(″CCJ.DAT″,″wb″))==NULL)/*打开文件*/{printf(″不能打开文件!″);

exit(0);

}for(i=0;i<=50;i++)/*写入数据*/fwrite(x+i,4,1,fp);

fclose(fp);/*关闭文件*/}

写入数据也可以整体一次完成:

fwrite(x,4,50,fp);

(1)文件的建立在操作系统下可通过改向操作完成。

(2)数据源文件也可通过任何字处理软件建立。

(3)执行一个向打印机写的操作,可在程序中实现数据的打印输出。例如:

fp=fopen(″PRN:″,″w″);

fputs(″HUNANCOMPUTER″,fp);/*打印输出HUNANCOMPUTER*/打印输出也可直接使用系统提供的打印机文件指针stdprn。11.3.7文件的读取控制

是不是处于文件尾部,可用文件结尾标志EOF来判断,还可用feof( )函数来判断,即

(1) while(fgetc(fp)!=EOF) {读取数据}(2) while(!feof(fp)){读取数据}

对于二进制文件,由于最后一个数据可能为−1(EOF),因此最好用feof( )函数控制读取。当然,读文件前应先打开文件,读完数据后应该关闭文件。

例11-3

从上例建立的文件CCJ.DAT中读出学生的C语言成绩,求出每个学生与平均成绩之差。/*程序11-3,求每个学生与平均成绩之差*/structst{char*name;

floatcj;}C[200];/*假定学生人数不超过200人*/main(){inti=0,n;

floatsum=0,av;

floatsav[200];/*与平均成绩之差*/FILE*fp;FILE*fp;if((fp=fopen("CCJ.DAT","rb"))==NULL)/*打开文件*/{printf("不能打开文件!");

exit(0);}while(!feof(fp))/*读数据,同时进行累加*/{fread(c+i,6,1,fp);

sum+=c[i].cj;

i++;

}n=i;av=sum/n;/*求平均成绩*/for(i=0;i<n;i++)/*求与平均成绩之差并输出*/{sav[i]=c[i].cj−av;

printf("%s,%6.1f,%6.1f\n",c[i].name,c[i].cj,sav[i]);

}11.4文件辅助操作1.反绕函数函数原型:

voidrewind(FILE*fp);功能:使文件的读写位置指针返回文件开头。2.随机定位函数

函数原型:

intfseek(FILE*fp,longintnumbytes,intorigin);

功能:将文件的位置指针移动numbytes个字节,numbytes为正数表示后移,为负数表示前移。其中移动的开始位置由origin确定,origin的值可以为0、1、2,或SEEK-SET、SEEK-CUR、SEEK-END,分别代表“文件开头”、“当前位置”、“文件末尾”三个特殊位置。

例如:

(1)fseek(fp,100l,0);/*将文件的位置指针移动到离文件开头100个字节处*/(2)fseek(fp,50l,1);/*将文件的位置指针向前移动50个字节处*/(3)fseek(fp,-10l,2);/*将文件的位置指针向后移10个字节处*/利用随机定位函数实现对文件的随机读写。3.求当前读写位置函数函数原型:

longintftell(FILE*fp);功能:得到文件的当前读写位置指针,用相对于文件开头的位移量来表示。若出现调用错误,返回值为-1。4.出错检测函数

函数原型:

intferror(FILE*fp);功能:检查文件中各种输入输出函数调用是否出错。若得到的函数值为0,表示未出错;得到的函数值非0,表示出错。调用fopen()函数时,ferror初值自动置0。5.初始化清零函数函数原型:

voidclearerr(FILE*fp);功能:清除文件错误标志和文件结束,将文件错误标志和文件结束标志置0。输入输出函数调用出错后,出错标志一直保留,直到对同一文件调用clearerr()函数、rewind()函数或任一输入输出函数。11.5程序设计举例

例11-4

从键盘输入若干字符,存入某磁盘文件中,然后从文件中读取数据打印输出。/*程序11-4,输入若干字符至文件,并打印输出*/main(){charch,*fname;

FILE*fp,*pp;

scanf(″%s″,fname);/*输入磁盘文件名*//*建立文件*/if((fp=fopen(fname,″w″))==NULL)

{printf(″文件不能打开!″);exit(0);

}ch=getchar( );/*从键盘读数据并写入文件fp*/while(ch!='\n'){fputc(ch,fp);

ch=getchar( );

}fclose(fp);/*从刚建立的磁盘文件中读取数据,并打印输出*/if((fp=fopen(fname,"r"))==NULL)/*打开数据文件*/{ printf("数据文件不能打开!");

exit(0);

}if((pp=fopen(″PRN:″,″w″))==NULL)

{printf(″打印机没能连接!″);

exit(0);

}ch=fgetc(fp);

while(!feof(fp))

{fprintf(pp,″%6c″,ch);

ch=fgetc(fp);

}fclose(fp);

fclose(pp);}

例11-5

学生信息包含有学号、姓名、年龄、成绩及住址,从键盘输入n个学生的这些信息,然后存入一个磁盘文件STUDENT.DAT中。算法提示:

(1)学生信息含有不同类型的数据,故用结构体数组描述。

(2)为方便使用,文件的建立用函数完成,学生信息写入文件时用fwrite()函数进行。程序如下:/*程序11-5,建立学生信息文件*/#defineSIZE200structstudent{intnum;

char*name;

intage;

floatscore;

char*addr;}stud[SIZE];/*学生数组*/intn;/*学生人数*/voidsave()/*建立文件STUDENT.DAT*/{FILE*fp;

inti;

if((fp=fopen(″STUDENT.DAT″,″wb″))==NULL)

{printf(″不能建立文件!″);

exit(0);

}for(i=0;i<n;i++)

if(fwrite(&stud[i],sizeof(structstudent),1,fp)!=1)

{printf(″文件不能写!\n″);

exit(0);

}fclose(fp);

}main(){inti;

scanf(″%d″,&n);

for(i=0;i<n;i++)/*从键盘输入数据*/scanf(″%d%s%d%f%s″,&stud[i].mum,stud[i].name,&stud[i].age,&stud[i].score,stud[i].addr);

save();/*调用函数建立文件*/}

例11-6

文件auto.dat存放了某道路同一时间各路段的车流信息,内容如下表。从文件中读取数据,计算各路段的车流量。车型路段1路段2路段3路段4BUS1001208098JEEP50997090TRUCK76234200190CAR234400365380MOTO800650700740/*例11-6,分段车流量计算*/main( ){ structat{char*name;

intnum[4];

}auto[5];/*原始数据*/FILE*fp;

inti,j;

intvehicle[4];/*输出数组*/if((fp=fopen("auto.dat","rb"))==NULL)/*打开文件*/{printf("不能打开文件!");

exit(0);}i=0;while(! feof(fp))/*读数据*/{fread(auto+i,10,1,fp);

i++;

}for(i=0;i<4;i++)/*计算车分段流量*/{vehicle[4]=0;

for(j=0;j<5;j++)vehicle[i]+=auto[j].num[i];

}printf("路段1路段2路段3路段4\n");for(i=0;i<4;i++)/*输出*/printf("%8d",vehicle[i]);}运行结果: 路段1路段2路段3路段41260150314151538

例11-7

编写类似DOS的拷贝命令的文件复制程序。算法提示:

(1)进行文件复制时需给出源文件与目标文件,程序中利用主函数的参数通过命令行获得。

(2)进行文件复制时反复从源文件中读,向目标文件写。程序如下:/*程序11-7,文件复制程序*/main(intargc,char*argv[]){inti;

FILE*fps,*fpt;

if(argc!=3){puts("命令行参数格式是:执行文件名源文件名目标文件名");exit(0);}if((fps=fopen(argv[1],"rb"))==NULL){printf("源文件不能打开!");

exit(0);

}if((fpt=fopen(argv[2],"wb"))==NULL){printf("目标文件不能建立!");

exit(0);

}while(!feof(fps)){fread(&i,2,1,fps);fwrite(&i,2,1,fpt);

}fclsoe(fps);fclose(fpt);}

例11-8

将例11-5建立的磁盘文件STUDENT.DAT首先在屏幕上输出文件内容,然后使指针移到开头,实现文件的复制。本题对文件的操作有显示输出和复制两种,但不是同时进行,故会涉及到指针移动,可用rewind( )函数将源文件指针移回文件开头。程序如下:/*程序11-8,文件的输出复制操作*/#defineSIZE200structstudent{intnum;

char*name;

intage;

floatscore;

char*addr;

}stud;main( ){FILE*fp1,*fp2;

char*tname;inti=0;if((fp1=fopen("STUDENT.DAT","rb"))==NULL){printf("不能打开文件!");

exit(0);

}while(!feof(fp1))/*屏幕输出*/{fread(&stud,sizeof(structstudent),1,fp1);printf("%6d%16s%8d%8.1f%28s\n",stud.mum,,stud.age,stud.score,stud.addr);}puts("请输入目标文件名");gets(tname);

rewind(fp1);if((fp2=fopen(tname,"wb"))==NULL){printf("不能建立文件!");

exit(0);

}while(!feof(fp1))/*复制文件*/{fread(&stud,sizeof(structstudent),1,fp1);

fwrite(&stud,sizeof(structstudent),1,fp2);

}fclose(fp1);

fclose(fp2);}

例11-9

某书店库存数据保存在库存文件BK中,每天的销售数据保存在销售文件BX中。编写程序,根据当天的销售数据调整库存文件。算法提示:

(1)用一临时文件BT先保存调整后的库存。

(2)从库存文件BK中读出库存数据减去从销售文件BX中读出的对应销售数据进行库存调整,写入临时库存文件BT。

(3)操作完毕,将临时库存文件BT改名为原库存文件BK。程序如下:

/*程序11-9,文件合并操作*/ structbook {char*name;

温馨提示

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

评论

0/150

提交评论