280 likes | 490 Views
例: 在考生目录下,有 Modify.c 程序,该程序中“ N ” 是根据程序功能需要填充部分,请完成程序填充(注意:不得加行、减行、加句、减句, 该程序功能:输入 n 和平面上 n 个点的坐标,计算各点间距离的总和。. #include <stdio.h> #include <math.h> #define f(x1,y1,x2,y2) sqrt(pow(x2-x1,2)+pow(y2-y1,2) // 带参数的宏 1 // #include <stdlib.h> 或 #include <malloc.h> void main( )
E N D
例:在考生目录下,有Modify.c程序,该程序中“N ”是根据程序功能需要填充部分,请完成程序填充(注意:不得加行、减行、加句、减句,该程序功能:输入n和平面上n个点的坐标,计算各点间距离的总和。
#include <stdio.h> #include <math.h> #define f(x1,y1,x2,y2) sqrt(pow(x2-x1,2)+pow(y2-y1,2) //带参数的宏 1 // #include <stdlib.h>或#include <malloc.h> void main( ) { float *x,*y,s=0; int i,j,n; scanf(“%d”,&n); x=(float)malloc(sizeof(float)n*2); y=x+n ; for(i=0;i<n;i++) scanf(“%df%f”,x+i,y+i); for(i=0;i<n-1;i++) for(j=0;j<n;j++) s+=f(x[i],y[i],x[j],y[j]);//指针的下标表示法为实参 printf(“%.2f\n”,s); } Void *malloc(unsigned size)在动态存储区分配一个长度为size的连续空间,其函数值是该区间的起始地址。若此函数未能成功的执行,则函数值为0。这里x、y是一点的纵横坐标的地址,所有的横坐标的地址排在所有纵坐标之前。
第十三章 文件 在前面的程序中,是把数据保存到内存变量里,数据的处理完全由程序控制。当程序运行结束后,所有变量被释放。 另外,一般程序都会有数据的输入/输出,如果输入/输出的数据量不大,则在程序运行时通过键盘输入可解决;当输入/输出量很大时,就不方便了。 文件就是解决上述问题的有效办法。把程序中使用的大量数据,通过编辑工具事先存储在磁盘文件中,得以长期保存。当程序运行时就从这个数据文件中读入,从而实现数据一次输入多次使用。 同样,当有大量数据输出时,可以将其输出到指定文件中,不受屏幕大小限制,且任何时候都可查看文件结果。一个程序的运行结果还可作为另外程序的输入。
13.1 C文件概述 • 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位 使用数据文件的目的 1、数据文件的改动不引起程序的改动——程序与数据分离 2、不同程序可以访问同一数据文件中的数据——数据共享 3、能长期保存程序运行的中间数据或结果数据 • 文件分类 • 按存储介质: • 普通文件:存储介质文件(磁盘、磁带等) • 设备文件:非存储介质(键盘、显示器、打印机等) • 按数据的组织形式: • 文本文件: ASCII文件,每个字节存放一个字符的ASCII码 • 二进制文件:数据按其在内存中的存储形式原样存放
文件类型指针 • 指针变量说明: FILE *fp; • fp是一个指向FILE类型结构体的指针变量; • 从而fp通过该结构体变量中的文件信息能够访问该文件; • 用法: • 文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息,访问文件 • 文件关闭后,它的文件结构体被释放
含义 文件使用方式 “r/rb” (只读) 为输入打开一个文本/二进制文件 “w/wb” (只写) 为输出打开或建立一个文本/二进制文件 “a/ab” (追加) 向文本/二进制文件尾追加数据 “r+/rb+” (读写) 为读/写打开一个文本/二进制文件 “w+/wb+” (读写) 为读/写建立一个文本/二进制文件 “a+/ab+” (读写) 为读/写打开或建立一个文本/二进制文件 例 文件打开与测试 FILE *fp; fp=fopen(“aa.c”,“w”); if(fp==NULL) { printf(“File open error!\n”); exit(0); } • 13.3文件的打开与关闭 • C文件操作用库函数实现,包含在stdio.h • 文件使用方式:打开文件-->文件读/写-->关闭文件 • 系统自动打开和关闭三个标准文件: • 标准输入------键盘 stdin • 标准输出------显示器 stdout • 标准出错输出-----显示器 stderr • 打开文件fopen • 函数调用: FILE *fp fp=fopen(char *name,char *mode) 例 FILE *fp; char *filename=“c:\\fengyi\\bkc\\test.dat” fp= fopen(filename,”r”); 例 FILE *fp; fp= fopen (“c:\\fengyi\\bkc\\test.dat”,”r”); 使用文件方式 • 功能:按指定方式打开文件 • 返值:正常打开,为指向文件结构体的指针;打开失败,为NULL 要打开的文件名
缓冲文件系统: 输入文件缓冲区 磁盘文件 程序数据区 a fclose 输出文件缓冲区 • 文件关闭fclose • 作用:使文件指针变量与文件“脱钩”,释放文件结构体和文件指针 • 函数调用:fclose(fp) • 功能:关闭文件指针fp所指向的文件 • 返值:正常关闭为0;出错时,非0 文件打开时返回的文件类型指针 不关闭文件可能会丢失数据
13.4文件的读写函数 • 字符I/O函数: fputc与fgetc • fputc • 函数调用:fputc(ch, fp) • 功能:把一字节代码ch写入fp指向的文件中 • 返值:正常,返回ch;出错,为EOF • fgetc • 函数调用:ch=fgetc(fp) • 功能:从文件指针fp所指向的文件中读取一个字节代码 • 返值:正常,返回读到的代码值;读到文件尾或出错为EOF 文件I/O与终端I/O #define putchar( c ) fputc(c,stdout) #define getchar( ) fgetc(stdin)
#include <stdio.h> main() { FILE *fp; char ch,*filename=“out.txt”; if((fp=fopen(filename,"w"))==NULL) { printf("cannot open file\n"); exit(0); } printf("Please input string:"); ch=getchar(); while(ch!='#') { fputc(ch,fp); putchar(ch); ch=getchar(); } fclose(fp); } 例 文件拷贝 将字符ch存入fp所指的文件中 将字符ch显示的屏幕上 获得一个字符存入ch 中 #include <stdio.h> main() { FILE *in, *out; char ch,infile[10],outfile[10]; scanf("%s",infile); scanf("%s",outfile); if ((in = fopen(infile, "r"))== NULL) { printf("Cannot open infile.\n"); exit(0); } if ((out = fopen(outfile, "w"))== NULL) { printf("Cannot open outfile.\n"); exit(0); } while (!feof(in)) fputc(fgetc(in), out); fclose(in);fclose(out); } 例从键盘输入字符,逐个 存到磁盘文件中,直到 输入‘#“为止 判断二进制文件是否结束 while(!feof(fp)) { c=fgetc(fp); …….. } #include <stdio.h> main() { FILE *fp; char ch,*filename=“out.txt”; if((fp=fopen(filename,”r"))==NULL) { printf("cannot open file\n"); exit(0); } while((ch=fgetc(fp))!=EOF) putchar(ch); fclose(fp); } 例 读文本文件内容, 并显示 • feof • 函数原型: int feof(FILE *fp) • 功能:判断文件是否结束 • 返值:文件结束,返回真(非0);文件未结束,返回0
fread(buffer, size, count, *fp) fwrite(buffer, size, count, *fp) • 数据块I/O:fread与fwrite • 函数调用: • 功能:读/写数据块 • 返值:成功时返回读/写的块数;出错或到文件尾返回0 • 说明: • buffer:指向要输入/输出数据块的首地址的指针 • size:每个要读/写的数据块的大小(字节数) • count:要读/写的数据块的个数 • fp: 要读/写的文件指针(对文件指针fp所指的文件进行读写操作)。 • fread与fwrite 一般用于二进制文件的输入/输出
例 float f[2]; FILE *fp; fp=fopen(“aa.dat”,“rb”); fread(f,4,2,fp); for(i=0;i<2;i++) fread(&f[i],4,1,fp); 例 struct student { int num; char name[20]; char sex; int age; float score[3]; }stud[10]; for(i=0;i<10;i++) fread(&stud[i],sizeof(struct student),1,fp);
例 从键盘输入4个学生数据,把他们转存到磁盘文件中去 void save() { FILE *fp; int i; if((fp=fopen("d:\\fengyi\\exe\\stu_dat","wb"))==NULL) { printf("cannot open file\n"); return; } for(i=0;i<SIZE;i++) if(fwrite(&stud[i],sizeof(struct student_type),1,fp)!=1) printf("file write error\n"); fclose(fp); } void display() { FILE *fp; int i; if((fp=fopen("d:\\fengyi\\exe\\stu_dat","rb"))==NULL) { printf("cannot open file\n"); return; } for(i=0;i<SIZE;i++) { fread(&stud[i],sizeof(struct student_type),1,fp); printf("%-10s %4d %4d %-15s\n",stud[i].name, stud[i].num,stud[i].age,stud[i].addr); } fclose(fp); } #include <stdio.h> #define SIZE 2 struct student_type { char name[10]; int num; int age; char addr[15]; }stud[SIZE]; main() { int i; for(i=0;i<SIZE;i++) scanf("%s%d%d%s",stud[i].name,&stud[i].num, &stud[i].age,stud[i].addr); save(); display(); }
fprintf(fp, format[,argument,…]) fscanf(fp, format[,address,…]) • 格式化I/O:fprintf与fscanf • 函数调用: • 功能:按格式对文件进行I/O操作 • 返值:成功,返回I/O的个数;出错或文件尾,返回EOF 例 fprintf(fp,“%d,%6.2f”,i,t); //将i和t按%d,%6.2f格式输出到fp文件 fscanf(fp,“%d,%f”,&i,&t); //若文件中有3,4.5 ,则将3送入i, 4.5送入t
字符串I/O: fgets与fputs • 函数调用: fgets(s, n, fp) fputs(s, fp) • 功能:从fp指向的文件读/写一个字符串 • 返值: • fgets正常时返回读取字符串的首地址;出错或文件尾,返回NULL • fputs正常时返回写入的最后一个字符;出错为EOF fputs把s指向的字符串写入fp指向的文件 fgets从fp所指文件读n-1个字符送入s指向的内存区, 并在最后加一个‘\0’ (若读入n-1个字符前遇换行符或文件尾(EOF)即结束)
#include <stdio.h> main() { FILE *fp1,*fp2; fp1=fopen("d:\\fengyi\\bkc\\ch12_4.c","r"); fp2=fopen("d:\\fengyi\\bkc\\ch12_41.c","w"); while(!feof(fp1)) putchar(fgetc(fp1)); rewind(fp1); while(!feof(fp1)) fputc(fgetc(fp1),fp2); fclose(fp1); fclose(fp2); } • 13.5文件的定位 • 几个概念 • 文件位置指针-----指向当前读写位置的指针 • 读写方式 • 顺序读写:位置指针按字节位置顺序移动,叫~ • 随机读写:位置指针按需要移动到任意位置,叫~ • rewind函数 • 函数调用: rewind(fp) • 功能:重置文件位置指针到文件开头 • 返值:无 例 对一个磁盘文件进行显示和复制两次操作
main() { int i; FILE *fp; if((fp=fopen("studat","rb"))==NULL) { printf("can't open file\n");exit(0); } for(i=0;i<3;i+=2) { fseek(fp,i*sizeof(struct student_type),0); fread(&stud[i],sizeof(struct student_type),1,fp); printf("%s %d %d %s\n", stud[i].name,stud[i].num,stud[i].age,stud[i].addr); } fclose(fp); } #include <stdio.h> struct student_type { int num; char name[10]; int age; char addr[15]; }stud[3]; • fseek函数 • 函数调用: fseek(fp, offset, whence) • 功能:改变文件位置指针的位置 • 返值:成功,返回0;失败,返回非0值 起始点 文件开始SEEK_SET 0 文件当前位置SEEK_CUR 1 文件末尾SEEK_END 2 文件指针 位移量(以起始点为基点,移动的字节数) >0向后移动 <0向前移动 • ftell函数 • 函数调用: ftell(fp) • 功能:返回位置指针当前位置(用相对文件开头的位移量表示) • 返值:成功,返回当前位置指针位置;失败,返回-1L, 例 fseek(fp,100L,0); fseek(fp,50L,1); fseek(fp,-10L,2); 例 磁盘文件上有3个学生数据,要求读入第1,3学生数据并显示
13.6出错的检测 • ferror函数 • 函数调用: ferror(fp) • 功能:测试文件是否出现错误 • 返值:未出错,0;出错,非0 • 说明 • 每次调用文件输入输出函数,均产生一个新的ferror函数值,所以应及时测试 • fopen打开文件时,ferror函数初值自动置为0
#include <stdio.h> int main(void) { FILE *stream; stream = fopen("DUMMY.FIL", "w"); getc(stream); if (ferror(stream)) { printf("Error reading from DUMMY.FIL\n"); clearerr(stream); } if(!ferror(stream)) printf("Error indicator cleared!"); fclose(stream); return 0; } • clearerr函数 • 函数调用: clearerr(fp) • 功能:使文件错误标志置为0 • 返值:无 • 说明:出错后,错误标志一直保留,直到对同一文件调clearerr(fp)或rewind或任何其它一个输入输出函数 例 ferror()与clearerr()举例
#include <stdio.h> main() { FILE *fp1,*fp2,*fp3; char ch; fp1=fopen("a.txt","r"); fp2=fopen("b.txt","r"); //以只读方式打开文件a和b fp3=fopen("c.txt","w"); //以写方式打开文件c while((ch=fgetc(fp1))!=EOF) fputc(ch,fp3); while((ch=fgetc(fp2))!=EOF) fputc(ch,fp3); fclose(fp1); fclose(fp2); fclose(fp3); } 1.有两个磁盘文件“A”和“B”,各存放一行字母,今要求把这两个文件中的信息合并输出到一个新文件“C”中去。
2.有5名学生,每名学生有3门课的成绩,从键盘输入以下数据(包括学生号,姓名,三门课成绩),计算出平均成绩,将原有数据和计算出的平均分数存放在磁盘文件“stud”中2.有5名学生,每名学生有3门课的成绩,从键盘输入以下数据(包括学生号,姓名,三门课成绩),计算出平均成绩,将原有数据和计算出的平均分数存放在磁盘文件“stud”中 #include <stdio.h> #define N 5 struct student { char num[9]; char name[20]; float score[3]; float average; };
main( ) { int i,j; struct student stu[N]; FILE *fp; fp=fopen("stud.txt","a+"); for(i=0;i<N;i++) {printf("请输入第%d个学生的信息:\n",i+1); scanf("%s%s",stu[i].num,stu[i].name); stu[i].average=0; for(j=0;j<3;j++) {scanf("%f",&stu[i].score[j]); stu[i].average=stu[i].average+ stu[i].score[j] /3; } }
for(i=0;i<N;i++) {fprintf(fp,"%s %s",stu[i].num,stu[i].name); for(j=0;j<3;j++) fprintf(fp,"%4.0f", stu[i].score[j]); fprintf(fp,"%4.0f\n", stu[i].average); } }
3.以下程序将磁盘中的一个文件复制到另一个文件中。两个文件名在命令行给出,将程序补充完整。3.以下程序将磁盘中的一个文件复制到另一个文件中。两个文件名在命令行给出,将程序补充完整。 # include <stdio.h> main (int argc,char * argv[ ]) {FILE * f1, * f2; char ch; if (argc<3 ) { printf (“参数个数不对!\n"); exit (0);} if (((f1 =fopen (argv [1],"r")) == NULL)||((f2 =fopen (argv [2],"r")) == NULL)) { printf (“不能打开文件!\n"); exit (0); } while (!feof(f1)) fputc (fgetc (f1), (f2)); fclose (f1); fclose (f2); } }
4.给定程序的功能是:调用函数fun将指定源文件中的内容复制到指定的目标文件中,复制成功时函数返回值为1,失败时返回0。在复制的过程中,把复制的内容输出到终端屏幕。主函数中源文件名放在变量sfname中,目标文件名放在变量tfname中。4.给定程序的功能是:调用函数fun将指定源文件中的内容复制到指定的目标文件中,复制成功时函数返回值为1,失败时返回0。在复制的过程中,把复制的内容输出到终端屏幕。主函数中源文件名放在变量sfname中,目标文件名放在变量tfname中。 #include <stdio.h> int fun(char *source, char *target) { FILE *fs,*ft; char ch; if((fs=fopen(source,"r"))==NULL) return 0; /*打开源文件*/ if((ft=fopen(target, "w"))==NULL) return 0; /*打开目标文件*/
printf("\nThe data in file :\n"); ch=fgetc(fs); /*在源文件中取一个字符*/ while(!feof(fs)) /*是否到文件尾?*/ { putchar( ch ); /*把从文件中读到的字符显示到屏幕上*/ fputc(ch,ft); /*把字符ch存到目标文件中*/ ch=fgetc(fs); /*在源文件中取一个字符*/ } fclose(fs); fclose(ft); printf("\n\n"); return 1; }
main( ) { char sfname[20] ="d:\\myfile1.txt“; char tfname[20]="d:\\myfile2.txt"; FILE *myf; int i; char c; myf=fopen(sfname,"w"); for(i=1;i<30;i++) /*往文件sfname中写字符并显示到屏幕上*/ {c='A'+rand( )%25; fprintf(myf,"%c",c); printf("%c",c); } fclose(myf);printf("\n\n"); if (fun(sfname, tfname)) printf("Succeed!"); else printf("Fail!"); } 调用函数fun进行文件内容复制
5.输入若干个学生的姓名、学号、数学、英语、计算机成绩到文件中student.dat。5.输入若干个学生的姓名、学号、数学、英语、计算机成绩到文件中student.dat。 #include <stdio.h> main ( ) { FILE *fp; char name[8],numb[8]; int m,e,c,n,i; scanf(“%d”,&n); fp=fopen(“student.dat”,“w”); for(i=1;i<=n;i++){ scanf(“%s%s%d%d%d”,name,numb,&m,&e,&c); fprintf(fp,“%s%s%d%d%d\n”,name,numb,m,e,c); } fclose(fp); }