You are on page 1of 33

C 语言程序设计 2A

第九次课
文 件
( FILE )
学过的文件库函数
FILE *fopen(“ 文件名”,“操作方式” );
int fclose(FILE *fp)

int fputc(int c, FILE *fp)


int fgetc(FILE *fp)

int feof(FILE *fp);

两个特殊的标识符
FILE 文件类型名
EOF 文件结束符号常数( -1 )
课堂练习
 程序 filecopy.c 的功能是:实现文件的复制,源文件名和目标文件名由命令行参数

指定,如 filecopy test1.txt test2.txt 这个命令行中, test1.txt 为源文件, test2.txt 为


目标文件,程序执行后会将 test1.txt 文件的内容复制到 test2.txt 文件中。
#include <stdio.h>
if ((destFile = fopen(————, "wb")) == NULL)
#include <stdlib.h>
{
int main(int argc, char *argv[])
fclose(srcFile);
{
printf(" 无法打开目标文件 \n");
FILE *srcFile, *destFile;
exit(3);
int ch;
}
if (argc != 3)
while ((ch = fgetc(srcFile)) != EOF)
{
{
printf(" 输入参数有误 .\n");
————————;
exit(1);
}
}
printf("succeful to copy a file!\n");
if ((srcFile = fopen(————, "rb")) == NULL)
fclose(srcFile);
{
fclose(destFile);
printf(" 无法打开源文件 \n");
return 0;
exit(2);
}
}
读一个字符串── fgets( )
函数原型:
char *fgets(char *s,int n,FILE *fp)

1. 功能:从 fp 所指文件读 n-1 个字符送入 s 指向的内存区 , 并在最

后加一个’ \0’ 。注:若读入 n-1 个字符前遇换行符或文件尾

( EOF )即结束。

2. 返回值:正常时返回读取字符串的首地址;

出错 或文件尾( EOF) ,返回 NULL

3. 参数: s 为读取字符串的地址, n 为读取字符的个数加 1 (自动

加‘ \0’ ), fp 为读取文件的文件指针
写一个字符串── fputs( )
函数原型:
int fputs(char *s,FILE *fp)

1. 功能:将 s 所指向的字符串写入 fp 指向的文件中。


注:不自动加换行符
2. 返回值:写入成功返回非负数( 0 );失败为 EOF
3. 参数: s 为字符串的地址, fp 为写入文件的文件指针
读/写一个字符串── fgets( ) 和 fputs( )
#include <stdio.h>
[ 案例 3] 将磁盘文件中的字 #include <stdlib.h>
int main(void)
符串读出,并显示在屏幕上。 {
FILE *fp;

思考:如何将整个文件读完? char string[81];

if((fp=fopen("d:\\in.txt","r"))==NULL)

{
printf("cann't open file");
exit(0);
}

if(fgets(string,81,fp)!=NULL)
fputs(string,stdout);
fclose(fp);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
[ 案例 3+] 将磁盘文件中 int main(void)
的字符串读出,并存储在 {
FILE *fp,*fp1;
另外一个文件中。
char string[81];

if((fp=fopen("d:\\in.txt","r"))==NULL)
{
printf("cann't open file");
exit(-1);
}
if((fp1=fopen("d:\\write.txt","w"))==NULL)
{
printf("cann't open file");
exit(-1);
}

while(fgets(string,81,fp)!=NULL)
fputs(string,fp1);
fclose(fp);
fclose(fp1);
return 0;
} 8
案例分析
读一个数据块── fread( )
函数原型:
int fread(void *buffer , int size , int count , FILE *fp) ;

1. 功能:从 fp 所指向的文件读一个数据块

2. 返回值:成功,返回值为 count; 失败为 0

3. 参数: buffer 是存放读入数据的起始地址(即存放何处) ;

size 为读取的字节数;

count 为读取的次数;

fp 为文件类型指针。

10
写一个数据块── fwrite( )

函数原型:
int fwrite(void *buffer , int size , int count , FILE *fp) ;

1. 功能:向 fp 所指文件写一个数据块

2. 返回值:成功,返回值为 count; 失败为 0


3. 参数: buffer 是要写入的数据在内存中的起始地址 ;
size 为写的字节数;
count 为写的次数,
fp 为文件类型指针。

fread( ) 和 fwrite( ) 函数,一般用于二进制文件的处理。


11
[ 案例 4] 将 4 个学生数据,转存到磁盘文件中去,再从文
件读出显示到屏幕上

typedef struct student


分析(构思): { char name[10];
( 1 )建立学生信息的结构体; int num;
int age;
( 2 )定义文件指针; }StudType;
( 3 )定义结构体数组并初始化(为方便调试);
( 4 )将学生信息写入文件,写完后关闭该文件(编写函数)

( 5 )再次打开该文件,读出所有学生信息,读完后关闭该文
件(编写函数) ;
( 6 )显示学生信息到屏幕上(编写函数) 。
[ 案例 4] 从键盘输入 4 个学生数据,把他们转存到磁盘文
件中去,再从文件读出显示到屏幕上

int save( StudType stud[] ,int n);


分析(构思):
int readfile(StudType stud[] );
( 1 )建立学生信息的结构体;
void display(StudType stud[],int
n);
( 2 )定义文件指针;
( 3 )定义结构体数组并初始化(为方便调试);
( 4 )将学生信息写入文件,写完后关闭该文件(编写函数)

( 5 )再次打开该文件,读出所有学生信息,读完后关闭该文
件(编写函数) ;
( 6 )显示学生信息到屏幕上(编写函数) 。
[ 案例 4] 从键盘输入 4 个学生数据,把他们转存到磁盘文
件中去,再从文件读出显示到屏幕上

分析(构思):
( 1 )建立学生信息的结构体;
( 2 )定义文件指针;
( 3 )定义结构体数组并初始化(为方便调试而作);
( 4 )将学生信息写入文件,写完后关闭该文件(编写函数)

( 5 )再次打开该文件,读出所有学生信息,读完后关闭该文
件(编写函数) ;
( 6 )显示学生信息到屏幕上(编写函数) 。
typedef struct student
{ char name[10]; int save( StudType stud[] ,int n);
int num; int readfile(StudType stud[] );
int age; void display(StudType stud[],int
}StudType; n);

int main(void)
{
StudType stud[10]={{“ 大师兄” ,201008,18},
{“ 二师弟” ,201009,19},
{“ 师父” ,201010,10}};
StudType result_stud[10];
int n;
if( save(stud,3) ==0) printf("save error");
if((n= readfile(result_stud) )==0) printf("save error");
display(result_stud,n);
return 0;
}
int save(StudType stud[],int n)
{ FILE *fp;
int count;
if((fp=fopen(“d:\\student.dat","wb"))==NULL)
{
printf(" 打不开文件 \n");
return 0;
}
if((count=fwrite(stud,sizeof(StudType),n,fp))==0)
printf(" 写操作错误 \n");
fclose(fp);
return count;
}
int readfile(StudType stud[])
{ FILE *fp;
int n;
int count=0;
if((fp=fopen(“d:\\student.dat”, “rb”))==NULL)
{
printf(“ 打不开文件 \n” );
return 0;
}
n=fread(stud,sizeof(StudType),1,fp);
while(n==1)
{
count++;
n=fread(&stud[count],sizeof(StudType),1,fp);
}
fclose(fp);
return count;
}
void display(StudType stud[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%-10s %4d %4d\n",stud[i].name,
stud[i].num,stud[i].age);
}
printf("\n____________________________________\
n");
}
课堂练习
 在以上设计的基础上,再编写一个函数实现追加一个学

生记录到文件中。

int addfile(StudType stud) ;


 以“追加”方式打开文件;

 写文件;

 关闭文件;
对文件进行格式化读/写── fscanf( ) 和 fprintf( )
函数
与 scanf( ) 和 printf( ) 函数的功能相似,区别在于: fscanf( ) 和
fprintf( ) 函数的操作对象是指定文件,而 scanf( ) 和 printf( ) 函数的操作
对象是标准输入( stdin )输出( stdout )文件。

int fprintf(FILE *fp,const char *format,[argument,…])


int fscanf(FILE *fp,const char *format, [argument,…])
功能:按格式对文件进行 I/O 操作
返值:成功 , 返回 I/O 的个数 ; 出错或文件尾 , 返回 EOF

例如, ......
int i=3; float f=9.80;
......
fprintf(fp,"%2d,%6.2f", i, f);
......
fprintf( ) 函数的作用是,将变量 i 按 %2d 格式、变量 f 按 %6.2f 格式,
以逗号作分隔符,输出到 fp 所指向的文件中:□ 3,□□9.80 (□表示 1 个
空格)。
用 fprintf 和 fscanf 实现学生信息文件的读和写

int save(StudType stud[],int n)


{ FILE *fp;
int count;
if((fp=fopen(“d:\\student.dat","wb"))==NULL)
{
printf(" 打不开文件 \n");
return 0;
}
for(i=0;i<n;i++)
{
fprintf(fp,"%s %d %d\
n",stud[i].name,stud[i].num,stud[i].age); }
fclose(fp);
return count;
}
int readfile(StudType stud[])
{ FILE *fp;
int n;
int count=0;
if((fp=fopen(“d:\\student.dat”, “rb”))==NULL)
{
printf(“ 打不开文件 \n” );
return 0;
}
n=fscanf(fp,"%s %d %d",stud[i].name,&stud[i].num,&stud[i].age);
while(n==3)
{
count++;
n= fscanf(fp,"%s %d %d",stud[i].name,&stud[i].num,&stud[i].age);
}
fclose(fp);
return count;
}
读/写函数的选用原则
从功能角度来说, fread( ) 和 fwrite( ) 函数可以完成文件的任何数据读/
写操作。

但为方便起见,依下列原则选用:

1 .读 / 写一个字符(或字节)数据时:选用 fgetc( ) 和 fputc( ) 函数。

2 .读 / 写一个字符串时:选用 fgets( ) 和 fputs( ) 函数。

3 .读 / 写一个(或多个)不含格式的数据时:

选用 fread( ) 和 fwrite( ) 函数。

4 .读 / 写一个(或多个)含格式的数据时:

选用 fscanf( ) 和 fprintf( ) 函数。


案例分析
位置指针与文件定位
文件中有一个读写位置指针,指向当前的读写位置。每次读写一

个(或一组)数据后,系统自动将位置指针移动到下一个读写位
置上。

 读写方式

顺序读写:位置指针按字节位置顺序移动

随机读写:位置指针按需要移动到任意位置

25
rewind( ) 函数

1 .函数原型: void rewind(FILE *fp);


2 .功能:使 fp 指向文件的位置指针返回到文件
头。

26
fseek( ) 函数
1. 函数原型: int fseek( 文件指针,位移量,参照点 );
int fseek(FILE *fp,long int offset,int whence)
2. 功能:将指定文件的位置指针,从参照点开始,移动指定的字节数。
3. 参数: fp 为文件指针,
whence 为参照点用 0 (文件头)、 1 (当前位置)和 2 (文件尾)表示
在 ANSI C 标准中,还规定了下面的名字:
SEEK_SET── 文件头, SEEK_CUR── 当前位置, SEEK_END── 文件尾
Offset 为位移量:以参照点为起点,正向偏移(当位移量 > 0时)或负向偏
移(当位移量 < 0时)的字节数。位移量一般被要求是 long 型数据,这样当
文件的长度大于 64K 时不出问题。
4. 返回值:成功为 0 ,失败为非 0.
注: fseek( ) 函数一般用于二进制文件。
注意:位移量一般被要求是 long 型数据。

fseek 函数调用的几个例子:
fseek(fp,100L,SEEK_SET); 将指针从文件头正向移动 100 个字节
fseek(fp,100L , SEEK_CUR); 将位置指针从当前位置正向移动
100 个字节
fseek(fp,-100L,SEEK_END) ; 将位置指针从文件末尾处负向偏移
100 个字节
返回文件当前位置的函数 ftell( )
由于文件的位置指针可以任意移动,也经常移动,往往容易迷
失当前位置, ftell( ) 就可以解决这个问题。
1 .用法: long int ftell( 文件指针 );
2 .功能:返回文件位置指针的当前位置(用相对于文件头的
位移量表示)。
如果返回值为 -1L ,则表明调用出错。
例如 :
offset=ftell(fp) ;
if(offset= = - 1L)
printf(“ftell( ) error\n”) ;

思考:如何获取文件长度(字节数)?
29
#include <stdio.h>
[ 案例 5] 磁盘文 #include <stdlib.h>
件上有 3 个学生 typedef struct student_type
数据,要求读入 {
char name[10];
第 2 学生数据并 int num;
显示。
int main(void) int age;
{ }STU;
int i=0;
FILE *fp;
STU st;
STU stud[]={{"mary",20110001,18},{"rose",20110002,19},{"mary",20110003,18}};
if((fp=fopen("d:\\stu.dat","wb+"))==NULL)
{
printf("can't open file\n");
exit(1);
}
fwrite(stud,sizeof(STU),3,fp);
fseek(fp,1*sizeof(STU),SEEK_SET);
fread(&st,sizeof(STU),1,fp);
printf("%s %d %d \n", st.name,st.num,st.age);
fclose(fp);
return 0;
30
}
出错检测
ferror( ) 函数
在调用输入输出库函数时,如果出错,除了函数返回值有所反映外,也可利用 ferror( )
函数来检测。
1 .用法: int ferror( 文件指针 ) ;
2 .功能:如果函数返回值为 0 ,表示未出错;如果返回一个非 0 值,表示出错。
( 1 )对同一文件,每次调用输入输出函数均产生一个新的 ferror( ) 函数值。因此在调用
了输入输出函数后,应立即检测,否则出错信息会丢失。
( 2 )在执行 fopen( ) 函数时,系统将 ferror( ) 的值自动置为 0 。
clearerr( ) 函数
1 .用法: void clearerr( 文件指针 ) ;
2 .功能:将文件错误标志(即 ferror() 函数的值)和文件结束标志(即 feof( ) 函数的值)
置为 0 。
对同一文件,只要出错就一直保留,直至遇到 clearerr( ) 函数或 rewind( ) 函数,或其它
任何一个输入输出库函数。

31
文件操作小结
分类 函数名 功能
打开文件 fopen( ) 打开文件
关闭文件 fclose( ) 关闭文件
fseek( ) 改变文件位置的指针位置
文件定位 rewind( ) 使文件位置指针重新置于文件开头
ftell( ) 返回文件位置指针的当前值
fgetc( ) 从指定文件取得一个字符
fputc( ) 把字符输出到指定文件
fgets( ) 从指定文件读取字符串
fputs( ) 把字符输出到指定文件
文件读写 fread( ) 从指定文件中读取数据项
fwrite( ) 把数据项写到指定文件
fscanf( ) 从指定文件按格式输入数据
fprintf( ) 按指定格式将数据写到指定文件中
feof( ) 若到文件末尾,函数值为真(非 0 )
文件状态 ferror( ) 若对文件操作出错,函数值为真(非 0 )
clearerr( ) 使 feof( ) 和 ferror( ) 函数值置零
课后作业
 所有课堂程序代码
 实验 11
 作业 4

33

You might also like