计算机程序设计基础课程教学PPT.ppt
乔 林,计算机程序设计基础,Email:Tel:62780973,清华大学计算机科学与技术系,第十章 文件与数据存储,学习目标掌握文件的基本概念学会使用常用的文件操作函数进行文件读写会使用文件存储、访问和管理数据,10.1 文件的基本概念,数据的保存与持久化在程序结束时数据仍有效文件的定义一组相关信息的集合存储于某种存储介质上具有某种特定格式,其中的信息也具有相同的含义,需要用不同的方法存取文件结构体与文件指针,文件的类型,顺序文件与随机文件顺序文件:只能顺序访问其中的信息例:存储在磁带上的文件只能顺序访问随机文件:可以随机访问文件的任一部分信息,可以指定读写位置二进制文件与文本文件文本文件:信息以字符形式存储,有分行信息,阅读目标为程序员与程序二进制文件:文件以二进制码存储,无分行信息,阅读目标为程序,10.2 基本文件操作,文件打开与关闭操作FILE*fopen(const char*filename,const char*mode);int fclose(FILE*fp);文件状态与缓冲区操作int feof(FILE*fp);int fflush(FILE*fp);文件指针操作void rewind(FILE*fp);int fseek(FILE*fp,long offset,int fromwhere);long ftell(FILE*fp);,10.2 基本文件操作,文件读写操作int fprintf(FILE*fp,const char*fmt,);int fscanf(FILE*fp,const char*fmt,);int fgetc(FILE*fp);char*fgets(char*str,int n,FILE*fp);int fputc(int ch,FILE*fp);char fputs(char*str,FILE*fp);int fread(void*buf,int size,int count,FILE*fp);int fwrite(void*buf,int size,int count,FILE*fp);,文件打开操作,函数原型FILE*fopen(const char*filename,const char*mode);返回值调用成功返回文件指针,失败返回NULL函数参数filename:文件名字符串,可以包含路径名mode:文件打开模式,文件打开模式,mode:文件打开模式r:读,若文件不存在,返回NULLw:写,若文件不存在,创建,若已存在,删除a:追加,若文件不存在,创建,若已存在,添加到文件尾部r+、w+:读写,若文件不存在,创建,若已存在,覆盖a+:读与追加,若文件不存在创建,若已存在,覆盖b:二进制格式示 例“rb”:读模式打开二进制文件“w+”:读写模式打开文本文件,文件打开示例,文件打开应用,#include#include int main()FILE*fp;char filename40,mode4;while(1)/*输入文件名和打开方式*/printf(“nEnter a filename:“);gets(filename);/*输入文件名*/printf(“nEnter a mode(max 3 characters):“);gets(mode);/*输入打开方式*/,文件打开示例,/*打开文件*/if(fp=fopen(filename,mode)!=NULL)printf(“nSuccessful opening%s in mode%s.n“,filename,mode);/*输出成功信息*/fclose(fp);/*关闭文件*/else fprintf(stderr,“nError opening file%s in mode%s.n“,filename,mode);/*输出不成功信息*/*询问是否结束*/puts(“Enter x to exit,any other to continue.“);if(getc(stdin)=x)break;else continue;,预定义的标准文件,标准文件:输入输出流stdin:标准输入设备,一般为键盘stdout:标准输出设备,一般为屏幕stderr:标准错误输出设备,一般为屏幕,文件关闭操作,函数原型关闭单个文件:int fclose(FILE*fp);关闭除标准文件之外的所有文件:int fcloseall();文件缓冲区外部块设备与内部数据流间的接口(中转站)清理文件缓冲区:int fflush(FILE*fp);清理所有文件的缓冲区:int fflushall();,文件关闭示例,将磁盘文件中的信息复制到新文件中,#include void main()FILE*in,*out;char inname12,outname12;scanf(“%s”,inname);scanf(“%s”,outname);if(in=fopen(inname,“r”)=NULL)exit(0);if(out=fopen(outname,“w”)=NULL)exit(0);while(!feof(in)fputc(fgetc(in),out);fclose(in);fclose(out);,文件格式化输入输出操作,函数原型格式化输出:int fprintf(FILE*fp,const char*fmt,);格式化输入:int fscanf(FILE*fp,const char*fmt,);说 明与标准格式化输入输出函数功能基本相同差别:多了文件指针参数,输入源或输出目的均是文件,而不是标准设备思考:fprintf(stdout,);=printf();?,文件格式化输出示例,将用户输入的 5 个浮点数写入文件,#include#include void clear_kb();int main()FILE*fp;float data5;int count;char filename20;puts(“Enter 5 floating-point numerical values.“);for(count=0;count5;count+)scanf(“%f“,/*清除键盘缓冲区*/,文件格式化输出示例,puts(“Enter a name for the file.“);gets(filename);if(fp=fopen(filename,“w“)=NULL)fprintf(stderr,“Error opening file%s.“,filename);exit(1);/*将数据写入文件和标准输出设备stdout*/for(count=0;count 5;count+)fprintf(fp,“ndata%d=%f“,count,datacount);fprintf(stdout,“ndata%d=%f“,count,datacount);fclose(fp);printf(“n“);return 0;/*清空键盘缓冲区*/void clear_kb()char junk80;gets(junk);,文件格式化输入示例,从文件中读取 5 个浮点数,#include#include int main()float f1,f2,f3,f4,f5;FILE*fp;if(fp=fopen(“INPUT.TXT“,“r“)=NULL)fprintf(stderr,“Error opening file.n“);exit(1);fscanf(fp,“%f%f%f%f%f“,文件字符输入输出操作,函数原型字符输入:int fgetc(FILE*fp);字符串输入:char*fgets(char*str,int n,FILE*fp);字符输出:int fputc(int ch,FILE*fp);字符串输出:char fputs(char*str,FILE*fp);说 明与标准字符输入输出函数功能相同差别:多了文件指针参数,源或目的均为文件,文件直接输入输出操作,函数原型直接输入:int fread(void*buf,int size,int count,FILE*fp);直接输出:int fwrite(void*buf,int size,int count,FILE*fp);说 明直接输入输出按块操作fread():从文件 fp 中将 count 块大小为 size 的连续数据读入缓冲区 buffwrite():将缓冲区 buf 中 count 块大小为 size 的连续数据写入文件 fp,文件直接输入输出示例,使用 fread()与 fwrite()进行直接文件访问,#include#include#define SIZE 20int main()int count,array1SIZE,array2SIZE;FILE*fp;/*数组初始化*/for(count=0;count SIZE;count+)array1count=2*count;/*打开一个二进制文件准备写入数据*/if(fp=fopen(“direct.txt“,“wb“)=NULL)fprintf(stderr,“Error opening file.“);exit(1);,文件直接输入输出示例,/*将数组array1存入文件*/if(fwrite(array1,sizeof(int),SIZE,fp)!=SIZE)fprintf(stderr,“Error writing to file.“);exit(1);fclose(fp);/*以二进制读方式打开文件*/if(fp=fopen(“direct.txt“,“rb“)=NULL)fprintf(stderr,“Error opening file.“);exit(1);/*从文件读取数据到array2中*/if(fread(array2,sizeof(int),SIZE,fp)!=SIZE)fprintf(stderr,“Error reading file.“);exit(1);fclose(fp);/*同时显示两个数组*/for(count=0;count SIZE;count+)printf(“%dt%dn“,array1count,array2count);return 0;,10.3 文件应用示例,如何将链表中的信息依次存入文件,然后再从文件中读出这些信息,恢复为链表,/childrenlist.h#include#includetypedef struct Child float height;float weight;int age;char gender;struct Child*next;ChildNode;void inputChild(ChildNode*child);ChildNode*createList(int n);ChildNode*createSortedList(int n);void printList(ChildNode*child);void saveList(FILE*fp,ChildNode*child);ChildNode*getList(FILE*fp);,10.3 文件应用示例,/childrenlist.c#include“childrenlist.h“void inputChild(ChildNode*child)/结点数据输入函数 printf(“Age:“);scanf(“%d“,10.3 文件应用示例,ChildNode*createList(int n)/生成链表 ChildNode*p,*child;int i;/建立一个空的头结点 child=(ChildNode*)malloc(sizeof(ChildNode);childnext=NULL;/初始化指针域 for(i=n;i 0;i)/依次建立并向表头插入结点/创建新结点 p=(ChildNode*)malloc(sizeof(ChildNode);inputChild(p);/输入数据到新结点/将新结点插入到表头结点之后 pnext=childnext;childnext=p;return child;,10.3 文件应用示例,ChildNode*createSortedList(int n)/生成有序链表 ChildNode*p,*q,*child;int i;child=(ChildNode*)malloc(sizeof(ChildNode);/头结点 childnext=NULL;/初始化指针域 for(i=n;i 0;i)/依次建立并向表头插入结点 p=(ChildNode*)malloc(sizeof(ChildNode);/创建结点 inputChild(p);/输入数据到新结点 q=child;/查找新结点的插入位置 while(qnext!=NULL,10.3 文件应用示例,void printList(ChildNode*child)/遍历并输出链表 ChildNode*current;current=child;/遍历指针初始状态指向表头 while(currentnext!=NULL)current=currentnext;/当前指针移动到下一个结点/输出当前结点数据 printf(“Age%dt“,currentage);printf(“Gender%ct“,currentgender);printf(“Height%ft“,currentheight);printf(“Weight%fn“,currentweight);,10.3 文件应用示例,void saveList(FILE*fp,ChildNode*child)ChildNode*current,*pre;/遍历指针初始状态指向表头之后的数据结点 current=childnext;while(current!=NULL)pre=current;current=currentnext;/当前指针移动到下一个结点 prenext=NULL;/结点指针域置空/存储当前结点数据 fwrite(pre,sizeof(ChildNode),1,fp);free(pre);,10.3 文件应用示例,ChildNode*getList(FILE*fp)ChildNode*p,*child;child=(ChildNode*)malloc(sizeof(ChildNode);childnext=NULL;p=(ChildNode*)malloc(sizeof(ChildNode);fread(p,sizeof(ChildNode),1,fp);/读入数据到新结点 while(!feof(fp)/依次建立并向表头插入结点/将新结点插入到表头结点之后 pnext=childnext;childnext=p;p=(ChildNode*)malloc(sizeof(ChildNode);fread(p,sizeof(ChildNode),1,fp);return child;,10.3 文件应用示例,/主文件#include#include#include“childrenlist.h“int main()ChildNode*childList=NULL,*childList2=NULL;int n;float f=1.0;FILE*fp;printf(“Number of children:“);scanf(“%d“,10.3 文件应用示例,childList=createSortedList(n);/建立有序链表 if(fp=fopen(“childlist.dat“,“wb“)=NULL)fprintf(stderr,“Error opening file.“);exit(1);saveList(fp,childList);/将链表存入文件 fclose(fp);if(fp=fopen(“childlist.dat“,“rb“)=NULL)fprintf(stderr,“Error opening file.“);exit(1);childList2=getList(fp);/从文件读出数据生成链表 fclose(fp);printList(childList2);/输出链表 return 0;,文件操作流程总结,步骤1:以某种模式打开文件判断文件是否成功打开步骤2:选择某种方式输入输出步骤3:关闭文件,FILE*fp;if(fp=fopen(inname,“r”)=NULL)while(!feof(fp)c=fgetc(fp);fclose(fp);,作 业,第295页:第二题(编程题)第1、7、10小题,