第12章 文件(课件)-《 C语言程序设计》同步教学(电子工业出版社)

2024-08-11
| 42页
| 101人阅读
| 7人下载
普通

内容正文:

第12章 文件 内容概述 文件分类  缓冲文件系统 文件的指针 文件打开与关闭 文件应用 教学目标 1.概述文件的概念,非缓冲文件系统和缓冲文件系统; 2.描述文件类型指针的概念及定义方法; 3.正确进行文件的打开和关闭操作,及对打开和关闭操作的错误处理; 4.正确使用文件的读写操作,包括基于字节,数据项等的读写操作; 5.牢记文件的随机读写方法; 6.正确使用文件访问的错误检测及处理方法; 12.1 文件概述 “文件”是指存储在外部设备上的、以唯一的名字作为标识的数据集合。 12.1.1 文本文件和二进制文件 文本文件 由一个一个字符组成,每一个字符用一个ASCII代码表示,如123.45以ASCII代码形式存储到磁盘需要6个字节。 特点:可通过显示器或打印机显示,即可读,比较直观。 二进制文件 是指以数据在内存中的存储形式原样输出存储到磁盘上的文件。如123.45在内存中以浮点数形式存储占4个字节,不管一个实数多大都占4个字节。  特点:节省存储空间,输入输出无需转换,速度快,不便阅读。 整数10 000以ASCII形式和二进制形式存储的差别 ASCII形式 00110001 00110000 00110000 00110000 00110000 00000000 00000000 二进制形式 00100111 00010000 文本文件一般占用存储空间较多,而且要花费转换时间(二进制与ASCII码之间的转换),但它便于对字符进行逐个处理。二进制文件的存储形式与其在内存中的存储形式相同,这样可以节省存储空间和转换时间,但1个字节并不对应1个字符,不能直接输出字符形式。 12.1.2 缓冲文件系统和非缓冲文件系统 缓冲文件系统(又称标准或高层文件系统) 特点:对程序中的每一个文件都在内存中开辟一个 “缓冲区”。 作用:从磁盘文件读入的数据先到“输入缓冲区”中, 然后再从缓冲区依次将数据送给接收变量。 变量 a 磁盘文件 内存 程序数据区 输入文件缓 冲区 ( 512 k ) 输出文件缓 冲区 ( 512 k ) 读 写 非缓冲文件系统 不由系统自动设置所需缓冲区,而由用户根据需要设置。 新的ANSI标准只建议使用缓冲系统,并对缓冲文件系统的功能进行了扩充,使既能用于处理字符代码文件,也能处理二进制文件。 12.2 文件类型指针 在缓冲文件系统中,系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区,该缓冲区用于存放文件正文。对文件的操作是通过文件指针实现的。 调用一个文件需要的信息: 文件当前读写的位置; 与该文件对应的内存缓冲区的地址; 缓冲区未被处理的字符数(字符指针); 文件的操作方式。 12.2.1 文件类型指针的定义 FILE数据结构定义在stdio.h头文件中,内容如下: typedef struct { int _fd; /*文件号*/ int _cleft; /*缓冲区中剩下的字符数*/ int _mode; /*文件操作方式*/ char *_next; /*文件当前读/写位置*/ char *_buff; /*文件缓冲区位置*/ }FILE; 例如,下面定义了一个文件类型指针: FILE *fp; 12.2.2 设备文件 C语言中把所有的外部设备都作为文件看待,这样的文件称为设备文件。 在程序开始运行时,系统自动打开三个标准文件,并分别定义了文件指针: stdin标准输入文件(键盘); stdout标准输出文件(显示器); stderr标准错误输出文件(显示器)。 12.3 文件的打开和关闭 打开文件:是在用户程序和操作系统之间建立联系,程序把所要操作的文件的有关信息,如文件名、文件操作方式(读、写或读/写)等通知给系统,系统为文件分配一个文件缓冲区。 调用形式: FILE *fp; fp=fopen("文件名","文件使用方式"); 功能:返回一个指向该文件的指针或错误标志NULL。 例如, fp=fopen("data.dat","r"); 文件的打开模式 打开模式 描 述 r 只读,打开已有文件,不能写 w 只写,创建或打开,覆盖已有文件 a 追加,创建或打开,在已有文件末尾追加 r+ 读写,打开已有文件 w+ 读写,创建或打开,覆盖已有文件 a+ 读写,创建或打开,在已有文件末尾追加 t 按文本方式打开 (缺省) b 按二进制方式打开 说明: (1)用"r"方式打开的文件只能在该文件已经存在的情况下向计算机输入数据,若文件不存在,则出错。 (2)用"w"方式打开的文件只能向该文件写数据,在该文件不存在的情况下,则建立以指定名字命名的文件,如果已经存在该文件,则在打开时删去该文件,然后重新建立一个新文件。 (3)用"a"方式向文件尾追加新的数据而不删除原有数据,要求文件必须首先存在。打开文件时,位置指针移到文件末尾。 (4)用“r+”、“w+”、“a+”方式打开的文件即可以用来输入数据,也可以用来输出数据。 (5)如果打开文件失败,则返回一个空指针NULL。 为增强程序的可靠性,常用下面的方法打开一个文件: if((fp=fopen("文件名","操作方式"))==NULL) { printf("can not open this file "); exit(0); } 12.3.2 文件的关闭fclose() 所谓关闭文件,即切断文件与程序的联系,释放文件缓冲区。 调用形式: fclose(文件指针) 例如: fclose(fp); 含义为关闭文件指针fp所指向的文件(即fp不再指向该文件)。如果正常关闭了文件,则函数返回值为0,否则,返回非零值。 12.4 文件读/写操作 字符读/写函数:fgetc()和fputc() 字符串读/写函数:fgets()和fputs() 数据块读/写函数:fread()和fwrite() 格式化读/写函数:fscanf()和fprintf() 使用这些函数都要求包含头文件stdio.h。 在C语言中提供了多种文件读/写的函数,常用的文件读/写函数如下: 12.4.1 字符读/写函数:fgetc()和fputc() 字符输出函数fputc() 调用形式: fputc(ch,fp); 作用: 将ch的值输出到fp所指向的文件中去,同 时将读/写位置指针向下移动1个字节(即 指向下一个写入位置)。 返回值:如果输出成功,则函数返回值就是输出的 字符数据,否则,返回一个符号常量EOF。 【例12.1】从键盘输入一些字符,写入到磁盘文件data.txt中,直到输入一个“#”为止。 #include <stdio.h> #include <stdlib.h> main( ) { FILE *fp; char str; if((fp=fopen("data.txt","w"))==NULL) /* 创建并打开data.txt文件 */ { printf("cannot open file "); exit(0); /* 打开不成功退出 */ } printf("请输入字符,以‘#’结束 "); while((str=getchar())!='#') /* 从键盘输入并判断是否为“#” */ fputc(str,fp); /* 写入到磁盘文件data.txt中 */ fclose(fp); /* 关闭文件 */ } 字符输入函数fgetc() 调用形式: ch=fgetc(fp); 作用:从指定的磁盘文件中读取一个字符。 对于文本文件,可以用文件结束标识EOF(-1)来判断文件结束;在对二进制文件执行读入操作时,必须使用库函数feof()来判断是否遇到文件尾。 feof()也适用于文本文件。 【例12.2】从例12.1建立的文件data.txt中读出所有的字符并显示在屏幕上。 #include <stdio.h> #include <stdlib.h> main() { FILE *fp; char ch; if((fp=fopen("data.txt","r"))==NULL) /*以读方式打开文件,且测试*/ { printf("cannot open file "); exit(0); /*打开不成功退出*/ } printf("文件data.txt中的内容为: "); while((ch=fgetc(fp))!=EOF) putchar(ch); /*当读取字符不为EOF时,把字符输出到显示器*/ fclose(fp); } 12.4.2 字符串读/写函数:fgets()和fputs() 字符串输出函数fputs() 调用形式: fputs(字符串,文件型指针); 作用: 向指定的文件写入一个字符串。 返回值:如果输出成功,返回值为0;否则,为非0值。 字符串输入函数fgets() 调用形式: fgets(str,n,fp); 作用: 从fp所指的文件中读出n1个字符送入字 符数组str中。如果在读入n1个字符结束 前遇到换行符‘ ’或EOF,读入结束。字符 读入结束最后加一个'\0'字符。 返回值:成功返回输入串的首地址,遇到文件结束 或出错返回NULL。 【例12.3】复制文本文件file1.txt的内容到file2.txt中。 #include<stdio.h> #include<stdlib.h> #include<string.h> main() { FILE *fp1,*fp2; char str [80]; if((fp1=fopen("file1.txt","r"))==NULL) /*以读方式打开文件,且测试*/ { printf("cann't open file"); exit(0); } if((fp2=fopen("file2.txt","w"))==NULL) /*以写方式打开文件,且测试*/ { printf("cann't open file"); exit(0); } while((fgets(str,80,fp1))!=NULL) /* 从文件file1.txt读取字符串 */ fputs(str,fp2); /* 一行字符串写入文件file2.txt */ fclose(fp1); fclose(fp2); } 12.4.3 数据块读/写函数:fread()和fwrite() ANSIC标准提出设置两个函数(fread()和fwrite())用来读/写一个数据块。它们的一般调用形式为 fread(buffer,size,count,fp); fwrite(buffer,size,count,fp); 其中: buffer表示存放读/写数据的首地址; size表示要读/写数据块的字节数; count表示要读/写多少个size字节的数据项; fp表示文件类型指针。 fread()和fwrite()函数,一般用于二进制文件的处理。例如: fwrite(buffer,50,32,fp); 【例12.4】从键盘输入4个学生的数据,写入文件stu.dat中,再读出这4个学生的数据显示在屏幕上。 〖程序分析〗 这是一个以数据块组织信息的实例,可以从以下几方面着手: 定义一个结构体类型,其中包括姓名、学号、年龄和地址几个数据项。定义一个结构体数组,把4个学生的数据输入结构体数组中。 定义save()函数,功能是将从键盘读入到结构体数组中的数据写到磁盘文件中。 定义display()函数,功能是读取文件的内容到结构体数组,然后输出到显示器。 在main()函数中输入学生的数据,调用以上两个函数实现学生数据的存储及显示功能。 #include <stdio.h> struct student { char name[10]; int num; int age; char addr[15]; }stud[4]; main() { void save(); /*函数声明*/ void display(); int i; printf("请输入学生数据 "); for(i=0;i<4;i++) /*输入4个学生的数据*/ scanf("%s%d%d%s", stud[i].name,&stud[i].num,&stud[i].age,stud[i].addr); save(); /*将从键盘读入到结构体数组中的数据写到磁盘文件中*/ printf("读取文件中的数据,并显示输出 "); display(); /*读取文件的内容到结构体数组,然后输出到显示器*/ } void save() /*将从键盘读入到结构体数组中的数据写到磁盘文件中*/ { FILE *fp; int i; if((fp=fopen("stu.dat","wb"))==NULL) { printf("cannot open file "); return; } for(i=0;i<4;i++) if(fwrite(&stud[i],sizeof(struct student),1,fp)!=1) printf("file write error "); fclose(fp); } void display() /*读取文件的内容到结构体数组,然后输出到显示器*/ { FILE *fp; int i; if((fp=fopen("stu.dat","rb"))==NULL) { printf("cannot open file "); return; } for(i=0;i<4;i++) { fread(&stud[i],sizeof(struct student),1,fp); printf("%8s %4d %5d %8s ", stud[i].name,stud[i].num,stud[i].age,stud[i].addr); } fclose(fp); } 程序运行情况如下: 请输入学生数据: Zhang 001 18 4-101↙ Wang 002 19 4-101↙ Li 003 18 4-102↙ Zhao 004 19 4-103↙ 读取文件中的数据并显示输出: Zhang 1 18 4-101 Wang 2 19 4-101 Li 3 18 4-102 Zhao 4 19 4-103 12.4.4 格式化读/写函数fscanf()和fprintf() 格式化读/写函数的调用格式如下: fscanf(文件指针,"格式符",输入变量首地址表); fprintf(文件指针,"格式符",输出参量表); printf()函数将输出按格式串规定输出到指定文件;scanf()函数从fp所指文件按格式串读入数据。函数执行成功返回读得的数据项个数;若在读第1项前已到达文件结束处,则返回EOF。 例如: int i=3;float f=9.80; fprintf(fp,"%2d,%6.2f",i,f); fscanf(fp,"%s%d%f",&va1,&var2,&var3); 【例12.5】从键盘读入学生信息后,用格式化方式写入磁盘文件中。 #include <stdio.h> #include <stdlib.h> main( ) { FILE *fp; char str[20]; int num; float score; if((fp=fopen("score.txt","w"))==NULL) /*以写方式打开文件并测试*/ { printf("File connot be opened "); exit(0); } printf("Please enter name number and score: "); scanf("%s%d%f",str,&num,&score); /*输入学生姓名、学号和成绩*/ while(score!=-1) { fprintf(fp,"%s%d%f",str,num,score); /*写入磁盘文件*/ scanf("%s%d%f",str,&num,&score); /*输入姓名、学号和成绩*/ } fclose(fp); } 12.5 文件定位函数 文件指针的重置函数rewind() 功能:将文件读/写指针移到文件开始位置,并将文件结束指示器和错误指示器清0。此函数无返回值。该函数适用于二进制文件和文本文件。 取文件的当前位置函数ftell() 功能:用于得到文件指针离开文件起点的偏移量(即偏移的字节数),如果函数调用出错(例如该文件不存在),则函数的返回值是-lL。例如: i=ftell(fp); if(i==-1L) printf("error "); 12.5.3 文件读/写指针定位函数fseek() 功能:用来将文件的读/写指针移动到指定的位置。 调用形式: fseek(fp,位移量,起始点); 其中: fp是已定义过的文件指针; “位移量”是相对于起始点的偏移量,要求是long型数据; “起始点”指明以什么地方为基准移动指针,可有3种取值。 起 始 点 名 字 数字表示 文件首 SEEK—SET 0 当前位置 SEEK—CUR 1 文件末尾 SEEK—END 2 若fseek()函数调用成功,返回值为0;否则返回一个非零值。 【例12.6】文件data1.txt的内容为This is a test.,分析以下程序的执行结果。 #include <stdio.h> #include <stdlib.h> #include <string.h> void main( ) { FILE *fp; int loc1,loc2; long d=81; char w; fp=fopen("data1.txt","r"); if (fp==NULL) printf("error "); else { loc1=fseek(fp,d,0); if (loc1==0) { w=fgetc(fp); printf("w=%c ",w); } } loc2=ftell(fp); rewind(fp); printf("loc2=%d ",loc2); loc2=ftell(fp); fclose(fp); printf("loc2=%d ",loc2); } 程序执行结果: w=a loc2=9 loc2=0 【例12.7】磁盘文件stu.dat上有4个学生数据,要求读出任意学生数据并显示。 #include <stdio.h> #include <stdlib.h> struct student { char name[10]; int num; int age; char addr[15]; }stud; main() { int n; FILE *fp; if((fp=fopen("stu.dat","rb"))==NULL) { printf("can't open file "); exit(0); } do { printf("Enter record number(1-4):"); scanf("%d",&n); }while(n<1||n>4); fseek(fp,(n-1)*sizeof(struct student),0); fread(&stud,sizeof(struct student),1,fp); printf("%s %d %d %s ",stud.name,stud.num,stud.age,stud.addr); fclose(fp); } 程序运行情况如下: Enter record number(1-4):2↙ wang 2 19 4-101 12.6 出错检测函数 ferror()函数 在各种输入/输出函数(如fputc()、fgetc()、fscanf()、fprintf()等)被调用时,如果出现错误,除了被调函数返回值有所反映外,还可以用ferror函数检查。 调用形式: ferror(fp); 返回值为0,表示未出错;否则,出错。 注意:ferror函数的值是最后一次调用时的出错状态。 clearerr()函数 将文件错误标志(即ferror函数的值)和文件结束标志(即feof函数的值)置为0。 调用形式: clearerr(文件指针); 练 习 程序设计题:统计满足条件x*x+y*y+z*z==2000的所有解的个数,并将统计结果以格式"%d"写入到新建的文件design.dat。 说明:若a、b、c是1个解,则a、c、b也是1个解,等等。 #include <stdio.h> void main() { FILE *p; int x,y,z,k=0; // // // // // // // } p=fopen("design.dat","w"); for(x=1;x<=sqrt(2000);x++) for(y=1;y<=sqrt(2000);y++) for(z=1;z<=sqrt(2000);z++) if((x*x+y*y+z*z)==2000) k++; fprintf(p,"%d", k); fclose(p); 练 习 程序设计题:在正整数中找出1个最小的、被3、5、7、9除余数分别为1、 3、5、7的数,将该数以格式"%d"写到新建文件design.dat。 #include <stdio.h> #include <math.h> void main() { // // // // // // // // } FILE *p; int x=0; p=fopen("design.dat","w"); do { x++; } while( !(x%3==1&& x%5==3&& x%7==5 && x%9==7)); fprintf(p,"%d",x); fclose(p); $$

资源预览图

第12章 文件(课件)-《 C语言程序设计》同步教学(电子工业出版社)
1
第12章 文件(课件)-《 C语言程序设计》同步教学(电子工业出版社)
2
第12章 文件(课件)-《 C语言程序设计》同步教学(电子工业出版社)
3
第12章 文件(课件)-《 C语言程序设计》同步教学(电子工业出版社)
4
第12章 文件(课件)-《 C语言程序设计》同步教学(电子工业出版社)
5
第12章 文件(课件)-《 C语言程序设计》同步教学(电子工业出版社)
6
由于学科网是一个信息分享及获取的平台,不确保部分用户上传资料的 来源及知识产权归属。如您发现相关资料侵犯您的合法权益,请联系学科网,我们核实后将及时进行处理。