第六章 文件.doc_第1页
第六章 文件.doc_第2页
第六章 文件.doc_第3页
第六章 文件.doc_第4页
第六章 文件.doc_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

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

文档简介

第6章文 件主要内容:C文件类型、文件打开方法和打开方式,文件读写、文件定位、出错检测等文件操作方法。教学要求:n 掌握C文件类型指针,文件的打开和关闭操作。n 熟练掌握文件读写等常用操作。n 学会使用文件进行程序设计。6.1 C文件概述所谓“文件”是指一组相关数据的有序集合。这个数据集有一个名称,叫做文件名。实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件(头文件)等。文件通常是驻留在外部介质(如磁盘等)上的,在使用时才调入内存中来。从不同的角度可对文件作不同的分类。从用户的角度看,文件可分为普通文件和设备文件两种。普通文件是指驻留在磁盘或其它外部介质上的一个有序数据集,可以是源文件、目标文件、可执行程序;也可以是一组待输入处理的原始数据,或者是一组输出的结果。对于源文件、目标文件、可执行程序可以称作程序文件,对输入输出数据可称作数据文件。设备文件是指与主机相联的各种外部设备,如显示器、打印机、键盘等。在操作系统中,把外部设备也看作是一个文件来进行管理,把它们的输入、输出等同于对磁盘文件的读和写。通常把显示器定义为标准输出文件,一般情况下在屏幕上显示有关信息就是向标准输出文件输出。如前面经常使用的printf,putchar函数就是这类输出。键盘通常被指定标准的输入文件,从键盘上输入就意味着从标准输入文件上输入数据。scanf,getchar函数就属于这类输入。从文件编码的方式来看,文件可分为ASCII码文件和二进制码文件两种。ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。ASCII码文件可在屏幕上按字符显示,例如源程序文件就是ASCII文件,用DOS命令TYPE可显示文件的内容。由于是按字符显示,因此能读懂文件内容。二进制文件是按二进制的编码方式来存放文件的。二进制文件虽然也可在屏幕上显示,但其内容无法读懂。C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。因此也把这种文件称作“流式文件”。本章讨论流式文件的打开、关闭和读、写等各种操作。6.1.1文件指针文件指针在语言中用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。定义说明文件指针的一般形式为:FILE *指针变量标识符;其中FILE应为大写,它实际上是由系统定义的一个结构,该结构中含有文件名、文件状态和文件当前位置等信息。在编写源程序时不必关心FILE结构的细节。例如:FILE *fp;表示fp是指向FILE结构的指针变量,通过fp即可找存放某个文件信息的结构变量,然后按结构变量提供的信息找到该文件,实施对文件的操作。习惯上也笼统地把fp称为指向一个文件的指针。文件的打开与关闭文件在进行读写操作之前要先打开,使用完毕要关闭。所谓打开文件,实际上是建立文件的各种有关信息,并使文件指针指向该文件,以便进行其它操作。关闭文件则断开指针与文件之间的联系,也就禁止再对该文件进行操作。FILE类型定义于头函数stdio.h中。因此凡是与文件有关的程序,须包括头文件stdio.h。6.1.2文件的打开方式C语言对文件操作时必须先声明对文件的操作方式(如新建、打开、追加等)和文件的类型。文件打开方式见表6-1所示。表6-1 C文件打开方式文件打开方式含 义r(只读)为输入打开一个文本文件w(只写)为输出打开一个文本文件a(追加)向文本文件尾追加数据rb (只读)为输入打开一个二进制文件wb (只写)为输出打开一个二进制文件ab (追加)向二进制文件尾追加数据r+ (读写)为读/写打开一个文本文件w+ (读写)为读/写建立一个新文本文件a+(读写)为读/写打开一个文本文件rb+ (读写)为读/写打开一个二进制文件wb+(读写)为读/写建立一个新二进制文件ab+(读写)为读/写打开一个二进制文件 注意凡文件打开方式后带“b”,表示文件是二进制文件;操作方式后带“+”,表示可读可写。r、w、a可以加上文本文件类型符t,写为rt、wt、at。6.2文件操作步骤与函数6.2.1 C文件操作函数C语言对文件操作可概括为三步:打开、使用、关闭。1. 打开文件文件打开使用fopen函数,一般打开文件所使用的代码为: FILE *fp; /* 定义文件指针 */ if(fp=fopen(文件名,文件使用方式)=NULL) printf(cannot open this filen);exit(0); 文件打开函数fopen(),告诉系统要打开的文件名、打开方式、打开的文件与哪一个文件指针相联系。至于加if判断,是为了做到“万无一失”,如当磁盘没有空间时,指针fp值为空NULL,则系统由exit(0)退出,程序不再往下执行。NULL在stdio.h中被定义为0,代表空指针。例如,可以用下边两行打开一个文本文件name.txt: FILE *fp; fp=fopen(name.txt,w);如果name.txt已存在,则打开,不存在则建立该文件。2. 关闭文件 fclose(文件指针);如fclose(fp);在对文件操作完毕后可关闭fp所执行的文件。 注意文件使用后必须关闭,其作用是将文件缓冲区的数据一次性写盘,否则将造成数据丢失!fclose()函数一次只能关闭一个文件。3文本文件读写函数C语言提供了较多的函数对文件内容进行读写,但是读者在使用时须区分文件是文本文件,还是二进制文件。前者多用于字符串的格式,后者多用于数值的格式。对以下各格式,设有定义:char ch,str80;int size,n,buffer20;FILE *fp;以下是常见的文件操作函数:l ch=fgetc(fp); 功能:从指定文件读取一个字符赋给内存变量ch。 l fgets(str,n,fp); 功能:从指定文件读出n-1个字符(串),将其首地址赋给变量str,并在串后自动加0。如:fgets(name,10,fp);表示从fp指向的文件中读取9个字符,赋给字符数组name。l fputc(ch,fp);功能:将内存中字符变量ch值写到文件fp中。如:fputc(k,fp);将字符k写到fp指定的文件中。l fputs(str,fp);功能:将内存中字符串str各字符写到文件fp中。如:fputs(china,fp);将字符串china写到fp指定的文件中。4数据文件读写函数l fscanf(文件指针,格式字符串,输入列表);功能:从文件按指定格式(类型)读入数据,放于对应的内存变量中。 如:fscanf(fp,%d,%f,&x,&y); 表示分别以int、float类型从fp指定的文件中读入两个数,放于内存变量x、y中。l fread(buffer,size,count,fp); 功能:从fp指向的文件中读count次(每次读size字节)数据项,放于内存buffer开始的地址中。执行成功,返回count。如:fread(float xx20,4,10,fp); 从fp指向的文件中读10个实数放于xx数组中。l fprintf(文件指针,格式字符串,输出项);功能:按指定格式(类型)将输出项值写到文件fp中。如:fprintf(fp,%d,%f,x,y);将内存变量x、y分别以int、float格式写到fp文件中。l fwrite(buffer,size,count,fp);功能:将内存buffer地址开始的count个数据项写往文件fp中。size为一个数据所占的字节数。执行成功,返回count。如:fwrite(xx,4,10,fp);表示将xx数组中10个实数写往fp指向的文件,每个数占4字节。至此,我们介绍了8个读写函数,初学者往往不知什么时候选用什么函数。从功能角度来说,fread()和fwrite()函数可以完成文件的任何数据读写操作。 提醒为方便起见,建议按下列原则选用函数:(1) 读/写1个字符(或字节)数据时:选用fgetc()、fputc()。(2) 读/写1个字符串时:选用fgets()、fputs()。(3) 读/写1个(或多个)不含格式的数据时:选用fread()、fwrite()。(4) 读/写1个(或多个)含格式的数据时:选用fscanf()、fprintf()。5判断文件读取结束函数feof(文件指针);功能:判断指针是否指向文件尾。若文件指针已经指到文件尾,则feof(fp)为1(真),否则feof(fp)为0(假)。 技巧判断某文件(二进制文件或文本文件)内容是否读完,常用到下面的语句格式: while(!feof(fp) ch=fgetc(fp); /*读取*/. /*其它操作/* 对文本文件,还可用下边的格式:while(ch=fgetc(fp)!=EOF) . 其中,EOF是一个常量,在头文件stdio.h内被定义为-1,代表文件结束符。6文件定位 对文件内容的读写,可以是顺序的,也可以随机的。当需要读写文件中任意位置的数据时,可用rewind()、 fseek()函数改变文件指针的值,从而使之指向不同的位置。l rewind(文件指针);功能:文件指针返回到文件开头。如rewind(fp); l fseek(文件指针,位移量,起始点); 对二进制文件,将文件指针从起始点开始移动指定的偏移量处。该函数主要用于从文件中随机读取数据。起始点值为:0表文件开始;1表文件当前位置;2表文件末尾。如fseek(fp,100L,0);将文件指针后移到距文件头100个字节处。fseek(fp,50L,1);将文件指针移到距当前位置50个字节处。fseek(fp,-10L,2);将文件指针指到从文件尾向后退10个字节处。6.2.2 文件程序阅读【例6-1】 从键盘上输入一组字符串,每个字符串用回车结束,输入空串表示输入结束。再将这些字符串写入到一个文本文件test1.txt中,然后用记事本打开这个文本文件查看输入的字符串内容。#include stdio.h /*文件操作头文件*/main() FILE *fp; char p80; /*每个字符串输入长度应该80个字符内*/ printf(input string: n); fp=fopen(test1.txt,w); /*打开文件*/ while(1) gets(p); /*输入字符串*/ if(strlen(p)=0) break; /*空串结束*/ fputs(p,fp); /*写字符串*/ fputc(n,fp); /*加入回车符*/ fclose(fp); /*关闭文件*/程序分析与解释:test1.txt文件在哪里?它和程序文件在同一个地方。如果先将程序存盘到指定地方,自然容易找到,倘若没有将程序存盘,那么它和默认程序noname.c在同一个地方。本程序使用的是写字符串函数fputs(p,fp),也可以使用写字符函数fputc(p,fp),将程序中写字符串一行换为如下语句行: for(j=0;jstrlen(p);j+) fputc(*(p+j),fp); /*写字符串*/【例6-2】 从磁盘文本文件中读入文本,然后显示在屏幕上。#include stdio.hmain() FILE *fp;char q80,*p=q,f80,ch;printf(text file name: );gets(f);fp=fopen(f,r);while(!feof(fp) ch=fgetc(fp); /*读一个字符*/ if(ch=n) *p=0;puts(q);p=q;/*遇回车符*/ else *p+=ch;fclose(fp);getch();程序分析与解释:对于任意的文本文件,如果事先不知道文字段有多长,从文件中读取文本时只能一个一个字符地读。本程序能读的文本文件和每个文字段都可以较长。如果是中西文的混合文字,若一个地方的半角字符个数是奇数时会出现乱码。程序中操作的文件名采取从键盘输入的方法,倘若该文件在默认目录内,直接输入文件名就行了,如果该文件不在默认目录内,则要加入文件的路径。【例6-3】 一维数组数据的写读。#include time.h#include stdlib.h#include stdio.h#define N 20main() int aN,bN,i,*p=b; FILE *fp; randomize(); for(i=0;iN;i+) ai=10+random(90); for(i=0;iN;i+) printf(%dt,ai); printf(n); fp=fopen(data1.dat,wb); for(i=0;iN;i+) fprintf(fp,%d,ai); /*写数据*/ fclose(fp); fp=fopen(data1.dat,rb); while(!feof(fp) fscanf(fp,%d,p+); /*读数据*/ fclose(fp); for(i=0;iN;i+) printf(%dt,bi);getch();程序分析与解释:程序先将数组a中数据写到数据文件中,然后再将数据文件中的数据读入到数组b中,两个数组中的数据都显示在屏幕上,如果显示内容相同,表示程序运行正确。写盘时数据与数据之间的分隔方式有三种:等宽分隔、逗号分隔、空格分隔,程序中用的是逗号分隔。但不管用哪种分隔方式,写盘和读盘必须相一致,否则不能正确读取。程序使用的是单数据写读函数,也可以采用块数据写读函数,将程序中写数据行和读数据行换用如下语句:写数据行:fwrite(a,2,20,fp);读数据行:fread(b,2,20,fp);此语句中的2是每个整数2个字节,若是实数则为4,20是20个数。块写函数和块读函数在写读时要相匹配,这与单数据写读的三种格式必须写读相匹配一样,它们之间是不能混用的。【例6-4】 二维数组数据的写读。#include time.h#include stdlib.h#include stdio.h#define N 10 /*数组行数*/#define M 6 /*数组列数*/main() float aNM,bNM,*pa=a,*pb=b,x; int i,j; FILE *fp; randomize(); for(i=0;iN;i+)for(j=0;jM;j+) x=random(900)/10.0+10; aij=x; for(i=0;iN;i+)for(j=0;jM;j+) printf(%.1ft,aij); fp=fopen(data2.dat,wb); for(i=0;iN;i+)for(j=0;jM;j+) fprintf(fp,%f ,*pa+); fclose(fp); printf(nn); fp=fopen(data2.dat,rb); while(!feof(fp) fscanf(fp,%f ,pb+); fclose(fp); for(i=0;iN;i+) for(j=0;jM;j+) printf(%.1ft,bij);getch();程序分析与解释:该程序首先用”wb”只读方式打开文件data2.dat,并且将二维数组a的数据读入到数组b中,两个数组中的数据都显示在屏幕上,如果显示内容相同,表示程序运行正确。 6.3精彩实例文件实现了程序与数据的独立性,同时使多个程序文件共享数据文件,这正是现代程序设计所倡导的思想。编写与文件有关的程序,首先要考虑将对文件以什么方式操作?文件能否被打开?文件在什么位置?文件的类型是什么?同时建议:为了程序的可读性,一般将文件的读取、存盘、操作分别自定义成函数;文件一旦操作完毕,最好立即关闭。【例6-5】阅读程序。将两个已经排好序的数据文件data1.dat和data2.dat合并成一个新文件data.dat,使得合并后的文件也是有序的(设数据从小到大排列)。并设data1.dat和data2.dat中的数据为16进制数,输出的数据文件data.dat中为10进制数。数据文件中的数据形式如:12,34,99,bc,ff,.程序源代码如下:#include stdio.hmain() FILE *f,*g,*h; int x,y; if(f=fopen(data1.txt,rb)=NULL) return 1; if(g=fopen(data2.txt,rb)=NULL) return 1; if(h=fopen(data.txt,wb)=NULL) return 1; fscanf(f,%x,&x); fscanf(g,%x,&y); while(!feof(f) & !feof(g) if(xy)fprintf(h,%d,x);fscanf(f,%x,&x); else fprintf(h,%d,y);fscanf(g,%x,&y); fprintf(h,%d,x);fprintf(h,%d,y); while(!feof(f) fscanf(f,%x,&x);fprintf(h,%d,x); while(!feof(g) fscanf(g,%x,&y);fprintf(h,%d,y); fclose(f); fclose(g); fclose(h); return 0 ;程序分析与解释:本程序中首先要注意文件的打开方式:以只读方式打开文件data1.dat和data2.dat,以只写方式打开文件data.dat,如果不存在,则建立一个新文件,如果存在则清空文件内容。然后通过fscanf函数取出文件data1.dat和data2.dat中的数据,比较大小,并将较小值存放在文件data.dat,以实现从小到大的排序功能。最后需要注意的是:文件一旦操作完毕,需要立即关闭。【例6-6】编制程序,完成输入3个学生的档案情况,包括:学号、姓名、性别、年龄、入学成绩,然后写入到文件xsda中。源程序代码如下:#include stdio.h#define N 3 /*人数*/char xmN9; /*定义二维数组保存姓名*/char xbN3; /*定义二维数组保存性别*/int xhN,ylN,i; /*定义数组保存学号,姓名*/float cjN,s; /* cjN保存成绩*/void indata() /* 此函数功能为接收数据信息保存在定义的空间*/ for(i=0;iN;i+) printf(%d#NO:,i+1);scanf(%d,&xhi); printf(%d#NAME:,i+1);scanf(%s,xmi); printf(%d#SEX:,i+1);scanf(%s,xbi); printf(%d#AGE:,i+1);scanf(%d,&yli); printf(%d#SCORE:,i+1);scanf(%f,&s);cji=s; void wdisk() /* 此函数功能为将接收到数据信息存入磁盘文件中*/ FILE *fp; fp=fopen(xsda.txt,w); for(i=0;iN;i+) fprintf(fp,%d %s %s %d %fn,xhi,xmi,xbi,yli,cji); fclose(fp);void rdisk()/* 此函数功能为从磁盘文件中读入学生信息*/ FILE *fp; fp=fopen(xsda.txt,r); for(i=0;iN;i+) fscanf(fp,%d %s %s %d %f,&xhi,xmi,xbi,&yli,&cji); fclose(fp);void disp()/* 此函数功能为显示学生信息*/ printf(NOtNAMEtSEXtAGEtSCOREn); for(i=0;iN;i+)printf(%dt%st%st%dt%.1fn,xhi,xmi,xbi,yli,cji); getch();main( ) /*主函数*/ int xh,x,y; indata( ); wdisk(); rdisk(); disp(); 程序分析与解释:该程序将文件的读取、存盘、操作分别自定义成函数,共由4个自定义函数和一个主函数构成。indata()函数的功能为从键盘输入学号、姓名、性别、年龄、入学成绩;wrdisk()函数的功能为将接受的学生信息存入到磁盘中;而rdisk()函数的功能为将学生信息从磁盘中取出;disp()函数的功能是显示学生信息。6.4 实训六文件复制一、实验目的1. 掌握C程序对任意文件的读写方法从而实现对文件的复制。2. 掌握带参主函数的C程序的运行方法。二、实验内容编制程序完成磁盘文件复制程序,类似于DOS下的copy命令。三、实验分析我们知道,在C语言的主函数和子函数之间可以进行参数传递,由主函数的实参传给子函数的形参。主函数main也是一个函数,它也可以带有形参,那又谁能够把实参传给它呢?只能是main的上级:DOS平台了。实际上,main函数可以有两个参数,这两个形参习惯上称为argc和argv,其中argv是一个指向字符串的指针数组,一般形式如下:main(argc,argv)int argc; char *argv ;或写成:main(int argc,char * argv);第一个形参argc是一个整型变量,第二个形参argv是一个指针数组,其元素指向字符型数据。main函数是由系统调用的,当处于操作命令状态下时,输入main函数所在文件名(经编译,连接后得到的可执行文件名),系统就调用main函数。main函数的实参是同命令一起给出的,也就是在一个命令行中包含命令名和需要传给main函数的参数,命令行的一般形式为:命令名 参数1 参数2参数nmain函数的两个参数中,argc是指命令行中参数的个数,命令名也作一个参数,argv是指针数组,argv0指向命令名,存放命令名字符串的首地址,argv1指向参数1,存放参数1的首地址,argv2指向参数2,存放参数2的首地址。对于本程序,设文件名为copyfile,在DOS下的命令格式为:copyfile 那么主函数main(int argc,char *argv)语句中,参数argc为整型,其值为3,argv为指针数组,argv0、argv1、argv2分别指向”copyfile”、 ”、”。四、实验步骤1. 编写C程序:#include stdio.hmain(int argc,

温馨提示

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

评论

0/150

提交评论