1 / 39

第十章 文件 10.1 文件概述 ■ 文件概念 所谓文件就是:存储在外部介质上 的信息集合。 根据存储的介质不同可分为: 磁盘文件 、 磁带文件 等。

第十章 文件 10.1 文件概述 ■ 文件概念 所谓文件就是:存储在外部介质上 的信息集合。 根据存储的介质不同可分为: 磁盘文件 、 磁带文件 等。 根据内容的不同可分为: 程序文件 、 数据 文件 等。. ■ 使用文件输入输出的必要性 这里主要讨论数据文件的输入输出,即如何将文件中的数据“输入”到程序的数据结构中,如何将程序的数据结构中的数据“输出”到文件中。 以往的输入输出方法: 键盘输入 ,屏幕输出。 这种方法不适用于数据量大的情况。 举例说明:.

herve
Download Presentation

第十章 文件 10.1 文件概述 ■ 文件概念 所谓文件就是:存储在外部介质上 的信息集合。 根据存储的介质不同可分为: 磁盘文件 、 磁带文件 等。

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十章 文件 10.1 文件概述 ■文件概念 所谓文件就是:存储在外部介质上 的信息集合。 根据存储的介质不同可分为: 磁盘文件、磁带文件等。 根据内容的不同可分为: 程序文件、数据文件等。

  2. ■使用文件输入输出的必要性 这里主要讨论数据文件的输入输出,即如何将文件中的数据“输入”到程序的数据结构中,如何将程序的数据结构中的数据“输出”到文件中。 以往的输入输出方法: 键盘输入 ,屏幕输出。 这种方法不适用于数据量大的情况。 举例说明:

  3. main() { int i, a[1000]; for(i=0;i<1000;i++) scanf(“%d”,a+i); ┊ for(i=0;i<1000;i++) printf(“%5d”,a[i]); } 缺 点: ①手工输入,效率低下,容易出错。 ②输出的数据不能保存,不便于进一步使 用。

  4. 采用文件输入输出可以克服这些缺点。 main() { int i, a[1000]; for(i=0;i<1000;i++) scanf(“%d”,a+i); ┊ for(i=0;i<1000;i++) printf(“%5d”,a[i]); } } 文件 文件

  5. ■C文件分类按在磁盘上存储的形式不同,可分为: 文本文件: 以ASCII字符存放—可见、可编辑、占空间大,读写效率低。 二进制文件:以二进制形式存放—可读性差、占空间小,读写效率高。使用时可根据需要选择。

  6. 10.2 文件类型指针 每个被使用的文件都在内存中开辟一个区,用来存放文件的有关信息(如文件名、文件状态及文件当前位置等)。这些信息保存在一个FILE类型的结构体变量中。 若 FILE *fp;则fp就称为指向文件类型的指针变量。访问文件通过文件指针进行。

  7. 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;

  8. 10.3 文件的打开与关闭 对文件的读写之前应“打开”该文件。 使用结束后“关闭”此文件。 ■文件的打开(fopen 函数) 用fopen函数实现对文件的打开。 fopen函数调用的一般形式: FILE *fp; fp=fopen(文件名,读写方式);

  9. 例如: fp=fopen(“a1.txt”, ”r”); 以只读方式打开文件a1.txt。 fopen函数返回指向a1.txt文件的指针,即fp是指向a1.txt文件的指针变量,往后就可以通过fp访问a1.txt文件。

  10. 文件读写方式: “r” 按只读方式打开一个文本文件 “w” 按只写方式打开一个文本文件 “a” 按追加方式打开一个文本文件 “rb” 按只读方式打开一个二进制文件 “wb” 按只写方式打开一个二进制文件 “ab” 按追加方式打开一个二进制文件

  11. 说明: (1)不能用”r”方式打开一个不存在的文 件,”r”方式只读不能写。 (2)“w”方式只写不能读,具有建立和 覆盖功能。 (3)调用fopen函数时,如果返回NULL则 表示打开不成功。

  12. ■文件的关闭(fclose 函数) 在使用完一个文件后应用fclose 函数关 闭文件,形式为: fclose(文件指针); 如:fclose(fp); 关闭后fp不再指向该文件。

  13. 10.4 文件的读写 文件打开后,就可以对它进行读写了。 ■文本文件的读写 即如何将以文本方式存放的文件输入到程序的数据结构中。如何将程序的数据结构中的数据以文本方式输出到文件中。 读对象:以文本方式存放的文件 写对象:以文本方式存放的文件

  14. 用于对文本文件读写的函数有: fscanf fprintf fgetc, getc fputc, putc fgets fputs 重点介绍 fscanf 和 fprintf。

  15. 以例子说明fscanf和fprintf的使用。 例:已知文本文件f1.txt中存放有100个学生的分数,要求读入这些数据,并按从高到低的顺序排序后输出到另一文件中。

  16. #include “stdio.h” void sort(int *a,int n) { ……} main() { int i,a[100]; FILE *fp; fp=fopen(“f1.txt”, “r”); if(fp==NULL) exit(0); 定义一个指向文件的指针变量 打开文件,使fp指向文件f1.txt

  17. for(i=0;i<100;i++) fscanf(fp,”%d”,a+i); fclose(fp); sort(a,100); fp=fopen(“f2.txt”, “w”); for(i=0;i<100;i++) fprintf(fp,”%4d”,a[i]); fclose(fp); } 从fp所指的文件中读数据 关闭fp所指的文件 注意:文本文件的输入格式要与 文件中的数据格式匹配。

  18. ■二进制文件的读写 (数据块) 即如何将以二进制方式存放的文件输入到程序的数据结构中。 如何将数据结构中的数据以二进制方式输出到文件中。 读对象:以二进制方式存放的文件 写对象:以二进制方式存放的文件 读写函数: fread fwrite getw putw

  19. 例:将前例中的排序结果改用二进制方式输出到文件f3.dat中。例:将前例中的排序结果改用二进制方式输出到文件f3.dat中。 #include “stdio.h” struct student { int num; char name[20]; int score; }; void sort (int *a,int n) { ……} main() { int i; struct student a[100]; FILE *fp; fp= f open(“f1.txt”, “r”); if(fp==NULL) exit(0);

  20. for(i=0;i<100;i++) fscanf(fp,”%d %s %d”,&a[i].num,&a[i].name,a[i].score); fclose1(fp); sort(a,100); fp=fopen(“f3.dat”, “wb”); for(i=0;i<100;i++) fwrite(a+i, sizeof(struct student), 1, fp ); fclose(fp); 文件的指针 数据的开始地址 数据的每一项的长度 数据的项数

  21. //将“f3.dat”数据读入内存并输出到屏幕 fp=fopen(“f3.dat”, “rb”); for(i=0;i<100;i++) { fread(a+i,sizeof(struct student),1,fp); printf(“num:%-5d name:%-10s score:% 3d”, a[i].num, a[i].name, a[i].score); } fclose(fp); }

  22. 10.5 文件的定位 文件中有一个位置指针,指向当前读写位置。如果顺序读写一个文件,每次读写完一个字符后,该位置指针自动指向下一个字符位置。如果想改变这样的规律,强制使位置指针指向指定位置,可以用有关函数。

  23. ■rewind函数 rewind函数的作用是使位置指针重返回文件的开头。 例:对文本文件f1.txt中的100个分数求超过平均分的人数。

  24. #include “stdio.h” main() { int i,a,n=0; float aver=0; FILE *fp; fp=fopen(“f1.txt”,“r”); for(i=0;i<100;i++) { fscanf(fp,”%d”,&a); aver+=a; } aver/=100; rewind(fp); for(i=0;i<100;i++) { fscanf(fp,”%d”,&score); if(score>aver) n++; } fclose(fp); printf(“\n %d”,n); }

  25. ■fseek函数和随机读写 使用fseek函数可以将位置指针指向所需的位置。 fseek函数调用的一般形式: fseek(文件指针,位移量,参考点); 以起始点为基准,向前移动的字节数 0 或 SEEK_SET 文件开始 1 或 SEEK_CUR 当前位置 2 或 SEEK_END 文件末尾

  26. 例:如果fp是指向一个存放100个整数的二进制文件,要读取第50个数到变量n时:例:如果fp是指向一个存放100个整数的二进制文件,要读取第50个数到变量n时: fseek(fp,sizeof(int)*(50-1),SEEK_SET); fread(&n, sizeof(int), 1,fp);

  27. 例:如果fp是指向一个存放100个整数的文本文件,并已知每个数按3位数字的定长格式存放,要读取第50个数到变量n时:例:如果fp是指向一个存放100个整数的文本文件,并已知每个数按3位数字的定长格式存放,要读取第50个数到变量n时: fseek ( fp, 3*(50-1), SEEK_SET ); fscanf ( fp, ”%3d”, &n); 若要从当前位置跳过10个数后读取一个数: fseek ( fp, 3*10, SEEK_CUR ); fscanf ( fp, ”%3d”, &n);

  28. 例:已知文本文件f5.dat中存放有100个学生的学号、姓名和考试成绩;要求从键盘输入任一学号,检索出相应学生的数据。例:已知文本文件f5.dat中存放有100个学生的学号、姓名和考试成绩;要求从键盘输入任一学号,检索出相应学生的数据。 说明: (1)文件f5.dat中每行为一个学生的数据,按定长格式存放,依次为:学号(整数,占5格)、姓名(占10格)、成绩(整数,占4格)。 (2)按学号从小到大的顺序连号存放,起始学号为1001。

  29. #include “stdio.h” typedef struct { int num; char name[20]; int score; }STU; main() { int no; STU st; FILE *fp;

  30. fp=fopen ( “f5.dat” , ”r” ); scanf ( “%d” , &no ); fseek ( fp, (no-1001)*19, 0 ); fscanf ( fp, ”%5d%10s%4d” ,&st.num ,st.name, &st.score ); printf (“\n%5d%10s%4d” , st.num , st.name, st.score ) ; fclose ( fp ) ; } 1001 LiLi 90 1002 WangPing 100 1003 HuHeng 75 ┊

  31. 上例的检索方法称为“定位检索”。 如果是非定长格式,则需要用“遍历检索”。 while ( !feof ( fp ) ) { fscanf ( fp, ”%d%s%d”, &st.num, st.name, &st.score ); if ( st.num==no ) { printf ( “\n%5d%10s%4d”, st.num, st.name, st.score ); break; } } 速度慢,但不受限制

  32. 综合例: 已知文本文件f1.dat中存放有武汉市所有公民的有关性别和年龄的数据,请编写程序分别找出其中10名男寿星和10名女寿星,并将20名寿星的数据以文本文件的方式存入到文件f2.dat中(先男后女)。

  33. 说明: ①文件f1.dat中每行为一个公民的数据,共有3项,依次为:姓名(不超过10个字符)、性别(0表示男,1表示女)和年龄(整数),项间以空格分隔。 ② 未给出公民个数,将文件中的数据读完为止。

  34. 算法思想: 开辟一个存放20名寿星数据的结果表a(结构体数组),然后逐个读取公民数据,每读取一个就向a中“判断插入”一个,男性公民往前段插,女性公民往后段插。

  35. 寿星表a 男性插入 Wanghao 0 100 Liming 0 98 ┊ wudan 1 99 xiaofang 1 95 ┊ 读一个公民的数据到p 女性插入 读完否? N Y

  36. #include <stdio.h> typedef struct { char name[10]; int sex; int age; } PEP;

  37. 插入函数,将一个公民的数据插入到寿星表void insert (PEP *a, int n, PEP t ){ int i,j; if ( t.age < a[n-1].age ) return ; for ( i =0; i<n; i++) if (t.age>a[i].age) break; for ( j=n-1; j>i; j--) a[j]=a[j-1]; 移位a[i]=t;插入}

  38. main() { int j; PEP p,a[20]; FILE *fp; fp=fopen (“f1.dat”,”r”); if(!fp) exit(0); for (j=0;j<20;j++) a[j].age=0; while( !feof ( fp ) ) { fscanf ( fp, ”%s%d%d”, p.name, &p.sex, &p.age ); insert (a+10*p.sex,10,p); } fclose(fp);

  39. fp=fopen(“f2.dat”,”w”); for(j=0;j<20;j++) fprintf(fp,”\n%15s%2d%5d”, a[j].name, a[j].sex,a[j].age ); fclose ( fp ); }

More Related