资源描述
自定义类型(自定义类型(typedef):):1.自定义类型(自定义类型(typedef):):将将C语言中的已有类型(包括已定义过的自定语言中的已有类型(包括已定义过的自定义类型)重新命名义类型)重新命名新的名称可以代替已有数据类型新的名称可以代替已有数据类型常用于简化对复杂数据类型定义的描述常用于简化对复杂数据类型定义的描述typedef ;1自定义类型(自定义类型(typedef)typedef ;typedef int INTEGER;int i,j;INTEGER i,j;typedef int*POINTER;int*p1;POINTER p1;2自定义类型(自定义类型(typedef)的使用方法)的使用方法定义变量定义变量 int i变量名变量名新类型名新类型名 int INTEGER加上加上 typedef typedef int INTEGER用新类型名定义变量用新类型名定义变量 INTEGER i;定义一个数组类型:定义一个数组类型:IntArrayint a10;int IntArray10;typedef int IntArray10;IntArray a;int a10;3Chap 12 文件文件12.1 将短句将短句“Hello World”写入到文件写入到文件 12.2 读取学生成绩文件读取学生成绩文件 12.3 文件复制文件复制 12.4 文件综合应用:个人小金库的管理文件综合应用:个人小金库的管理 4本章要点本章要点n什么是文件?什么是文件?C文件是如何存储的?文件是如何存储的?n什么是文本文件和二进制文件?什么是文本文件和二进制文件?n怎样打开、关闭文件?怎样打开、关闭文件?n怎样编写文件读写程序?怎样编写文件读写程序?n怎样编写程序,实现简单的数据处理?怎样编写程序,实现简单的数据处理?512.1 将短句将短句“Hello World”写入到文件写入到文件例例12-1 把短句把短句“Hello World!”保存到磁盘文保存到磁盘文件件f1.txt中。中。6#include#include int main(void)FILE*fp;/*定义文件指针定义文件指针*/if(fp=fopen(f1.txt,w)=NULL)/*打开文件打开文件*/printf(File open error!n);exit(0);fprintf(fp,%s,Hello World!);/*写文件写文件*/if(fclose(fp)/*关闭文件关闭文件*/printf(Can not close the file!n);exit(0);return 0;例例12-1 源程序源程序712.1.2 文件的概念文件的概念n文件:保存在外存储器上的一组数据的有序文件:保存在外存储器上的一组数据的有序集合集合n特点特点:数据数据长久保存长久保存 数据数据长度不定长度不定 数据按数据按顺序存取顺序存取812.1.3 文本文件和二进制文件文本文件和二进制文件 语言中的文件是数据流语言中的文件是数据流文件的两种数据形式:文件的两种数据形式:ASCII码码(文本文件(文本文件 text stream)字符流字符流 二进制码二进制码(二进制文件(二进制文件 binary stream)二进制文件是直接把内存数据以二进制形式保存。二进制文件是直接把内存数据以二进制形式保存。例如,整数例如,整数1234文本文件保存:文本文件保存:49 50 51 52(4个字符)个字符)二进制文件保存:二进制文件保存:04D2(1234的二进制数)的二进制数)字节字节.字节字节字节字节字节字节字节字节字节字节912.1.4 缓冲文件系统缓冲文件系统 内存单元内存单元 数据数据 文件文件由操作由操作系统自系统自动完成动完成程序控制程序控制磁盘速度慢磁盘速度慢,直接把数据直接把数据写到磁盘效率很低写到磁盘效率很低缓冲器缓冲器512字节字节内存单元内存单元1012.1.4 缓冲文件系统缓冲文件系统向磁盘输出数据:数据向磁盘输出数据:数据 缓冲区,装满缓冲区,装满缓冲区后缓冲区后 磁盘文件。磁盘文件。从磁盘读入数据:先从磁盘读入数据:先一次性一次性从磁盘文件将从磁盘文件将一批数一批数据输入据输入到缓冲区,然后再从缓冲区到缓冲区,然后再从缓冲区逐个逐个读入数据读入数据到变量到变量。数据数据 缓冲器缓冲器512字节字节文件文件由操作由操作系统自系统自动完成动完成程序控制程序控制 内存单元内存单元 内存单元内存单元11缓冲文件与文件类型指针缓冲文件与文件类型指针用文件指针指示文件缓冲区中具体读写的位置用文件指针指示文件缓冲区中具体读写的位置FILE *fp;数据数据缓冲器缓冲器512字节字节文件文件由操作由操作系统自系统自动完成动完成程序控制程序控制fp同时使用多个文件时,每同时使用多个文件时,每个文件都有缓冲区,用不个文件都有缓冲区,用不同的文件指针分别指示。同的文件指针分别指示。typedef struct short level;unsigned flags;FILE;第第242页页12n nFILEFILE:结构类型:结构类型:结构类型:结构类型n n用用用用 typedef typedef 定义定义定义定义,在头文件,在头文件,在头文件,在头文件中中中中typedef struct short level;/*缓冲区使用量缓冲区使用量 */unsigned flags;/*文件状态标志文件状态标志*/char fd;/*文件描述符文件描述符*/short bsize;/*缓冲区大小缓冲区大小*/unsigned char *buffer;/*文件缓冲区的首地址文件缓冲区的首地址*/unsigned char *curp;/*指向文件缓冲区的工作指针指向文件缓冲区的工作指针*/unsigned char hold;/*其他信息其他信息*/unsigned istemp;short token;FILE;2.文件结构文件结构FILE133.文件类型指针文件类型指针FILE*fp指向文件缓冲区,通过移动指针实现对文件的操作指向文件缓冲区,通过移动指针实现对文件的操作数据数据缓冲器缓冲器512字节字节文件文件由操作由操作系统自系统自动完成动完成程序控制程序控制fp同时使用多个文件时,每个文件都有缓冲区,用同时使用多个文件时,每个文件都有缓冲区,用不同的文件指针分别指示。不同的文件指针分别指示。如何使如何使fp与具体与具体文件文件挂挂钩?1412.2 读取学生成绩文件读取学生成绩文件例例12-2 已知一个数据文件已知一个数据文件f.txt中保存了中保存了5个学生的计算机等个学生的计算机等级考试成绩,包括学号、姓名和分数,文件内容如下级考试成绩,包括学号、姓名和分数,文件内容如下,请请将文件的内容读出并显示到屏幕中。将文件的内容读出并显示到屏幕中。301101 张文张文 91301102 陈慧陈慧 85301103 王卫东王卫东76301104 郑伟郑伟 69301105 郭温涛郭温涛 551512.2.1 程序解析程序解析#include stdio.hint main(void)FILE*fp;/*定义文件指针定义文件指针*/long num;char stname20;int score;if(fp=fopen(f.txt,r)=NULL)/*打开文件打开文件 */printf(File open error!n);exit(0);while(!feof(fp)fscanf(fp,%ld%s%d,&num,stname,&score);printf(%ld%s%dn,num,stname,score);if(fclose(fp)/*关闭文件关闭文件 */printf(Can not close the file!n);exit(0);1612.2.1 程序解析程序解析#include stdio.hint main(void)FILE*fp;/*定义文件指针定义文件指针*/long num;char stname20;int score;if(fp=fopen(f.txt,r)=NULL)/*打开文件打开文件 */printf(File open error!n);exit(0);while(!feof(fp)fscanf(fp,%ld%s%d,&num,stname,&score);printf(%ld%s%dn,num,stname,score);if(fclose(fp)/*关闭文件关闭文件 */printf(Can not close the file!n);exit(0);fopen(“文件名文件名 字符串字符串”,“打开方式打开方式 字符串字符串)使文件指针与相应文件实体对应起来使文件指针与相应文件实体对应起来程序对文件指针进行操作,即程序对文件指针进行操作,即fp代表磁盘文件代表磁盘文件n函数函数fopen()的返回值的返回值执行成功,则返回包含文件缓冲区等信息的执行成功,则返回包含文件缓冲区等信息的FILE型型地址地址,赋给,赋给文件指文件指针针fp不成功,则返回一个不成功,则返回一个NULL(空值)(空值)exit(0):关闭所有打开的文件,并终止程序的执行关闭所有打开的文件,并终止程序的执行参数参数0表示程序正常结束;非表示程序正常结束;非0参数通常表示不正常的程序结束参数通常表示不正常的程序结束17文件打开方式文件打开方式fp=fopen(f.txt,r)n文件打开方式参数表文件打开方式参数表18文件读写与文件读写与打开方式打开方式if 读文件读文件 指定的文件必须存在,否则出错;指定的文件必须存在,否则出错;if 写文件写文件(指定的文件可以存在,也可以不存在指定的文件可以存在,也可以不存在)if 以以 w 方式写方式写 if 该文件已经存在该文件已经存在 原文件将被删去重新建立;原文件将被删去重新建立;else 按指定的名字新建一个文件;按指定的名字新建一个文件;else if 以以 a 方式写方式写 if 该文件已经存在该文件已经存在 写入的数据将被添加到指定文件原有数据的后面,不会删去原来的内容;写入的数据将被添加到指定文件原有数据的后面,不会删去原来的内容;else 按指定的名字新建一个文件(与按指定的名字新建一个文件(与“w”相同);相同);if 文件同时读和写文件同时读和写 使用使用 r+、w+或或 a+打开文件打开文件 1912.2.1 程序解析程序解析#include stdio.hint main(void)FILE*fp;/*定义文件指针定义文件指针*/long num;char stname20;int score;if(fp=fopen(f.txt,r)=NULL)/*打开文件打开文件 */printf(File open error!n);exit(0);while(!feof(fp)fscanf(fp,%ld%s%d,&num,stname,&score);printf(%ld%s%dn,num,stname,score);if(fclose(fp)/*关闭文件关闭文件 */printf(Can not close the file!n);exit(0);2012.2.3 关闭文件关闭文件if(fclose(fp)printf(Can not close the file!n);exit(0);fclose(文件指针文件指针)把缓冲区中的数据写入磁盘扇区,确保写文件的正常完成把缓冲区中的数据写入磁盘扇区,确保写文件的正常完成释放文件缓冲区单元和释放文件缓冲区单元和FILE结构体,使文件指针与具体文结构体,使文件指针与具体文件脱钩。件脱钩。函数函数fclose()的返回值的返回值返回返回0:正常关闭文件:正常关闭文件返回非返回非0:无法正常关闭文件:无法正常关闭文件2112.3 文件复制文件复制例例12-3 已知一个文本数据文件已知一个文本数据文件f1.txt,请将该,请将该文件复制一份,保存为文件复制一份,保存为f2.txt。新建一个文本文件新建一个文本文件f1.txt,将该文件与源程序放在,将该文件与源程序放在同一目录下,执行程序,观察结果。同一目录下,执行程序,观察结果。22例例12-3 源程序源程序#include int main(void)FILE*fp1,*fp2;char c;if(fp1=fopen(f1.dat,r)=NULL)printf(File open error!n);exit(0);if(fp2=fopen(f2.dat,w)=NULL)printf(File open error!n);exit(0);while(!feof(fp1)c=fgetc(fp1);fputc(c,fp2);fclose(fp1);fclose(fp2);return 0;23打开多个文件打开多个文件if(fp1=fopen(f1.dat,r)=NULL)printf(File open error!n);exit(0);if(fp2=fopen(f2.dat,w)=NULL)printf(File open error!n);exit(0);C语言允许同时打开多个文件语言允许同时打开多个文件不同的文件对应不同的文件指针不同的文件对应不同的文件指针不允许同一个文件在关闭前再次打开不允许同一个文件在关闭前再次打开24文件读写函数文件读写函数n字符读写函数字符读写函数:fgetc/fputcn字符串读写函数:字符串读写函数:fputs/fgetsn格式化读写函数:格式化读写函数:fscanf/fprintfn二进制读写函数:二进制读写函数:fread/fwriten其他相关函数:其他相关函数:检测文件结尾函数检测文件结尾函数feof检测文件读写出错函数检测文件读写出错函数ferror清除末尾标志和出错标志函数清除末尾标志和出错标志函数clearerr文件定位的函数文件定位的函数fseek2512.3.2 字符读写函数字符读写函数fgetc和和fputcwhile(!feof(fp1)c=fgetc(fp1);fputc(c,fp2);n函数函数fputc()fputc(ch,fp);把一个字符把一个字符 ch 写到写到 fp 所指示的磁盘文件上所指示的磁盘文件上返回值返回值n-1(EOF):写文件失败:写文件失败nch:写文件成功:写文件成功26字符读写函数字符读写函数fgetc和和fputcn函数函数fgetc()ch=fgetc(fp);从从fp所指示的磁盘文件上读入一个字符到所指示的磁盘文件上读入一个字符到ch区分键盘字符输入函数区分键盘字符输入函数getchar()27从键盘输入从键盘输入10个字符,写到文件个字符,写到文件 f2.txt 中,再重新读出,中,再重新读出,并在屏幕上显示验证。并在屏幕上显示验证。键盘输入键盘输入 写入文件写入文件 f2.txt 读文件读文件 屏幕显示的过屏幕显示的过程程键盘输入键盘输入 f2.txt时,文件按写方式打开。时,文件按写方式打开。f2.txt 显示到屏幕时,文件按读方式打开。显示到屏幕时,文件按读方式打开。读和写是两种不同的操作,读和写是两种不同的操作,f2.txt 分别被打开和关闭两次。分别被打开和关闭两次。例例12-428源程序源程序int main(void)int i;char ch;FILE*fp;if(fp=fopen(f2.txt,w)=NULL)/*打开文件打开文件f2.txt */printf(File open error!n);exit(0);for(i=0;i 10;i+)/*写文件写文件10次次 */ch=getchar();fputc(ch,fp);if(fclose(fp)/*关闭文件关闭文件 */printf(Can not close the file!n);exit(0);if(fp=fopen(f2.txt,r)=NULL)/*打开文件打开文件f2.txt */printf(File open error!n);exit(0);for(i=0;i 10;i+)/*读文件读文件10次次 */ch=fgetc(fp);putchar(ch);if(fclose(fp)/*再次关闭文件再次关闭文件 */printf(Can not close the file!n);exit(0);return 0;2912.3.3 字符串方式读写函数字符串方式读写函数fgets和和fputsn函数函数fputs()fputs(s,fp);用来向指定的文本文件写入一个字符串用来向指定的文本文件写入一个字符串s:要写入的字符串,结束符:要写入的字符串,结束符0不写入文不写入文件。件。函数返回值函数返回值n执行成功,函数返回所写的最后一个字符执行成功,函数返回所写的最后一个字符n否则,函数返回否则,函数返回EOF30字符串方式读写函数字符串方式读写函数fgets和和fputsn函数函数fgets()fgets(s,n,fp);从文本文件中读取字符串从文本文件中读取字符串s:可以是字符数组名或字符指针;:可以是字符数组名或字符指针;n:指定读入的字符个:指定读入的字符个数;数;fp:文件指针:文件指针函数被调用时,最多读取函数被调用时,最多读取n-1个字符,并将读入的字符串存个字符,并将读入的字符串存入入s所指向内存地址开始的所指向内存地址开始的n-1个连续的内存单元中。个连续的内存单元中。当函数读取的字符达到指定的个数,或接收到换行符,或接收到文当函数读取的字符达到指定的个数,或接收到换行符,或接收到文件结束标志件结束标志EOF时,将在读取的字符后面自动添加一个时,将在读取的字符后面自动添加一个0字符;字符;若有换行符,则将换行符保留(换行符在若有换行符,则将换行符保留(换行符在0字符之前);若有字符之前);若有EOF,则不保留,则不保留函数返回值函数返回值n执行成功,返回读取的字符串;执行成功,返回读取的字符串;n如果失败,则返回空指针,这时,如果失败,则返回空指针,这时,s的内容不确定的内容不确定31将字符串将字符串apple,grape,pear 写入到磁盘文件写入到磁盘文件f12-5.txt中,然后再从该文中,然后再从该文件中读出,显示到屏幕。件中读出,显示到屏幕。int main(void)FILE*fp;char a 80=apple,grape,pear,strout80=;int i;if(fp=fopen(f12-5.txt,w)=NULL)printf(File open error!n);exit(0);for(i=0;i 0)/*表示有记录存在*/fseek(cfptr,size*(logcount-1),SEEK_SET);/*定位最后记录*/fread(&log,size,1,cfptr);/*读取最后记录*/printf(The last log is:n);printf(logid:%-6ldnlogdate:%-11snlognote:%-15sn,log.logid,log.logdate,log.lognote);printf(charge:%-10.2lfnbalance:%-10.2lfn,log.charge,log.balance);else printf(no logs in file!n);47增加日志增加日志void AddNewLog(FILE*cfptr)/*添加新记录*/struct LogData log,lastlog;long logcount;printf(Input logdate(format:2019-01-01):);scanf(%s,log.logdate);printf(Input lognote:);scanf(%s,log.lognote);printf(Input Charge:Income+and expend-:);scanf(%lf,&log.charge);logcount=getLogcount(cfptr);/*获取记录数*/48增加日志增加日志 if(logcount0)fseek(cfptr,size*(logcount-1),SEEK_SET);fread(&lastlog,size,1,cfptr);/*读入最后记录*/log.logid=lastlog.logid+1;/*记录号按顺序是上次的号+1*/log.balance=log.charge+lastlog.balance;else /*如果文件是初始,记录数为0*/log.logid=1;log.balance=log.charge;fseek(cfptr,0L,SEEK_END);/*rewind(cfptr);*/printf(logid=%ldn,log.logid);fwrite(&log,sizeof(struct LogData),1,cfptr);/*写入记录*/49计算日志个数计算日志个数long getLogcount(FILE*cfptr)/*获取文件记录总数*/long begin,end,logcount;fseek(cfptr,0L,SEEK_SET);begin=ftell(cfptr);fseek(cfptr,0L,SEEK_END);end=ftell(cfptr);logcount=(end-begin)/size;return logcount;50Any more operations?n修改一条日志修改一条日志n统计支出统计支出n统计收入统计收入n?51
展开阅读全文