文件—典型例题分析与解答
1 二制文件中的数据存放格式是__________方式,整数-12345要占用_________字节;文本文件的数据存放格式是_________方式,整数一12345要占用___________字节。
【分析】教材(pl73)中有明确说明,二进制文件的的数据是以二进制数方式存放的,其占的字节数就是该数据类型中规定的字节数(整型数据占用2个字节)。文本文件中的数据是ASCII代码方式存放的,数据中的每个字符都要占用1个字节。
【答案】二进制数
2
ASCII代码
6
2 如果要定义一个文件型指针fp,应该使用的定义语句是________________;同时,在程序清单的开头要有一条_________________命令。
【分析】文件型是系统在头函数“stdio.h”中定义的一种结构型,并且系统将其定义成用户自定义的数据类型,名称为“FILE”,所以程序中如果需要定义这种文件型指针,可以使用用户自定义的数据类型符“FILE”来定义。由于这个用户自定义的数据类型符是在头函数“stdio.h”冲定义的,所以程序的开头要使用包含文件命令将“stdio.h”包含到本程序清单中。
【答案】FILE *fp;
#inclde "stdio.h"
3 如果打开文件时,选用的文件操作方式为“wb+”,则下列说法中错误的是()
①要打开的文件必须存在 ②要打开的文件可以不存在
③打开文件后可以读取数据 ④要打开的文件是二进制文件
【分析】从教材(p174)中可以发现,打开文件时的操作方式中只要含有字符“w”,则这个文件可以存在,也可以不存在。当文件不存在时,系统会自动建立一个新文件。分析备选答案①:显然是错误的说法,是符合题意的答案。备选答案②显然是正确的说法。备选答案③的说法是正确的,因为文件操作方式中只要含有“+”号,文件就可以读写。备选答案④的说法也是正确的,因为文件操作方式中含有“b”字符,表示文件是以二进制文件方式处理的。
【答案】①
4 如果要求打开一个a盘根目录下、名为“ccw.dat”的二进制文件用于读和追加写,则调用打开文件函数的格式应为_________________;如果要求打开一个C盘一级目录ccw下、名为“ccw1.txt”的文本文件,并且用于只写,则调用打开文件函数的格式应为_____________________.
【分析】打开文件函数调用时需要确定两个参数:前一个是文件全名,后一个是文件操作方式。对本题的第1个空白来说,前一个参数是"a:\ccw. dat",后一个参数是”ab+”。对本题的第 2个空白来说,前一个参数是"c:\ccw\ccw1.txt",后一个参数是"w"。
【答案】 fopen("a:\ccw.dat","ab+")
fopen("c:\ CASEccw\ccw1.txt","w")
5 假设文件型指针f已经指向可写的磁盘文件,并且正确执行了函数调用“fputc('A',f)”,则该次调用后的函数返回值是___________________。
【分析】对于函数“fputc()”的返回值是这样规定的:正确写出了字符,则返回值就是这个字符;写字符出现错误,则返回值是符号常量EOF,其值为-1。
【答案】 字符'A' 或 整数65
6 如果要将存放在双精度型数组a[10」中的10个双精度型实数写到文件型指针fp1指向的文件中,正确的语句是()
① for(i=0;i<80;i++) fputc(a[i],fp1);
② for(i=0;i<10;i++) fputc(&a[i],fp1);
③ for(i=0;i<10;i++) fwrite(&a[i],8,l,fp1);
④ fwrite(fp1,8,10,a);
【分析】分析备选答案①:由于循环控制变量i的值依次为0、1、…、 79,将会出现a[10]、 a[11]、…、a[79]的下标越界,结果是错误的;此外, fputc()函数调用时的第1个实参是双精度型数据,不是字符型数据,也是错误的。分析备选答案③:函数fputc()调用时的第1个实参是地址,不是字符型数据,是错误的。分析备选答案③:循环执行10次,控制变量三的值依次等于0、1、…、9,每次输出的数据是从地址a[i]开始的8个字节,恰好是存放在数组元素a[i」中的一个双精度型数据,所以是正确的,符合题意。至于备选答案④:参数的顺序出现错误,第1个参数应该是输出数据的首地址,第4个参数应该是指向文件的文件型指针。
【答案】③
7 如果将主文件型指针fp指向的文件内部指针置于文件尾,正确的语句是()
①feof(fp); ②rewind(fp);
③fseek(fp,OL,0); ④fseek(fp,OL,2);
【分析】分析备选答案①:feof()函数的功能是测试文件尾,不是定位到文件尾;分析备选答案②:函数rewind()的功能是定位到函数头,不是定位到函数尾;分析备选答案③:该语句的功能是定位到离基准点(函数头)偏离0个字节的位置上,实际上是定位到文件头;只有备选答案④才符合题意。该答案中的语句是定位到离基准点(文件尾)偏离0个字节的位置上,就是文件尾的位置。
【答案】 ④
8 如果文件型指针fp指向的文件刚刚执行了一次读操作,则关于表达式“ferror(fp)'”的正确说法是()
①如果读操作发生错误,则返回1
②如果读操作发生错误,则返回0
③如果读操作没有发生错误,则返回1
④如果读操作没有发生错误,则返回0
【分析】函数ferror()是测试文件型指针所指向的文件最近一次的操作是否发生错误,如果发生错误,则返回非0,如果没有发生错误,则返回0,所以上述4个备选答案中,只有答案④是正确的答案。
【答案】④
9 假定有下列程序段,其中关于“while”语句功能的正确说法是()
if(((fp1=fopen("p1.c","r"))==NULL)¦¦
((fp2=fopen("p2.c","w"))==NULL)) exit(0);
while(feof(fp)) fputc(fgetc(fp1),fp2);
①程序中有语法错误
②什么功能也没有
③将p1.c文件复制到p2.c中
④将p2.c文件复制到pl.c中
【分析】分析这段程序,前一条语句是分别打开两个文件,其中 pl.c是只读方式打开的,并且使得文件型指针 fp1指向该文件;p2.c是只写方式打开的,并且使得文件型指针fp2指向该文件。然后执行 while语句,注意该循环语句的控制条件是“feof(fp1)”,这个函数调用的结果是:如果fpl指向的函数已经到达文件尾,则返回值为“非0”(逻辑真),否则返回值为“0”(逻辑假)。因为是刚刚打开p1.c文件,所以不应该是文件尾,条件将为0(假),退出循环。所以该循环语句什么也没有做。4个备选答案中,只有备选答案②符合题意。
【答案】②
10 下列程序是统计名为“pl.c”的文本文件中字符数目的,请为程序填写缺少的语句。
#include"stdio.h"
main()
{ FILE *fp;
long count= 0;
if((fp=fopen("p1.c","r"))==NULL)exit(0);
while(!feof(fp))
{___________________
count++;
}
printf("count=%1d\n",count);
fclose(fp);
}
【分析】程序中的前两条语句是定义文件型指针fp和整型变量count并且赋初值0。第3条语句是打开名为p1.c的文本文件用于只读操作。第5条语句是输出变量count中的统计结果的。关键是第4条while循环语句,控制循环的条件是“不是文件尾”,循环体中的第2条语句是变量count加1,注意,这个变量中将是统计文件p1.c中的字符数目的,显然所缺少的语句是读取文件中的单个字符的,所以需要填写的语句是
“fgetc(fp);”。
【答案】 fgetc(fp);
11 阅读下列程序,写出程序的主要功能。
#include”stdio.h”
main()
{ FILE *fp;
char ch;
long count1=0, count2=0;
if((fp=fopen("p1.c","r"))==NULL) exit(0);
while(!feof(fp))
{ ch=fgetc(fp);
if(ch=='{')countl++;
if(ch=='}')count2++;
}
if( count1==count2)
printf("YES!\n");
else
printf("ERROE!\n”);
fclose(fp);
}
【分析】本程序的关键是while语句,从控制该循环的条件(不是文件尾)来看,这个当型循环结构是依次处理文件中的所有数据的标准程序段。分析该循环语句的循环体,可以看出是分别统计文件中的字符'{'和'}'的数目,并分别存放在变量count1和count2中。退出循环后,比较这两个统计变量的值,如果相等,则输出“YES!”,如果不相等,则输出“ERROR!”。由此不难总结出本程序的基本功能。
【答案】如果文件p1.c中的“{”和“}”的数目不相等,则输出“ERROR!”;否则输出“YES!”。实际上,本程序是检查C语言源程序清单中的花括号是否配对。
12 假定名为“data1.dat”的二进制数据文件中依次存放了下列4个单精度实数:
-12.1、12.2、-12.3、12.4
阅读下列程序,写出运行该程序后的输出结果。
#include"stdio.h"
main()
{ FILE *fp;
float sum=0.0,x;
int i;
if((fp=fopen("data1.dat","rb"))==NULL) exit(0);
for(i=0;i<4;i++,i++)
{ fread(&x,4,l,fp);
sum+=x;
}
printf("%f\n",sum);
fclose( fp);
}
【分析】本程序的前4条语句比较简单,首先定义文件型指针;定义单精度变量sum和x,并给sum赋初值 0.0;定义整型变量i;然后打开datal.dat的二进制文件用于只读。接下来的for循环是关键,我们可以用记录变量值的方法记录运行结果,记录如下:
循环前: sum=0.0, i=0,循环控制条件i<4成立,开始循环。
第1次循环:从文件中读取4个字节的数据(单精度实数-12.1)存入x,加到变量sum中,sum值为0.0 +(-12.1);执行i++,i++,i为 2,循环控制条件i<4成立,继续循环。
第2次循环:从文件中读取4个字节的数据(单精度实数12.2)存入x,加到变量 sum中,sum值为一 12.1+12.2,结果是 0.1;执行 i++,i++,i为 4,循环控制条件 i< 4不成立,退出循环。最终输出的就是变量sum中的值,结果为0.1。
【答案】0.1
【说明】建立本程序要求读取数据的、名为“data1.dat”的二进制数据文件,可以使用下列程序:
#include”stdio.h”
main()
{ FILE *fp;
float x[4]={-12.1,12.2,-12.3,12.4 };
int i;
if((fp= fopen(”data1. dat”,”wb”))== NULL) exit(0);
for( i= 0; i< 4; i++)
fwrite( &x「 i」, 4, 1, fp);
fclose( fp);
}
13 编程序完成下列功能:从键盘读取40个人的姓名,每个姓名是一个字符串(长度要求<=20),存入名为“sname.txt”的文本文件中。
【说明】从文件中读取字符串时,一般要求以字符数目或者读到回车换行符为一个字符串结束(参看 fgets()的功能)。为了将来能正确读取本程序建立的文件中的字符串,要求从键盘上读取字符串后,在最后一个有效字符的后面插入一个回车换行符,然后再写入文件。
【分析】定义文件型指针,打开名为“sname.txt”文本文件用于只写操作。再设计一个次数为40的单重次数型循环,输入40个字符串并插入“回车换行符”写入指定的文件中。
【答案】 #include"stdio.h"
main()
{ FILE *fp;
int i;
char s[21];
if((fp=fopen("sname.txt","w"))==NULL) exit(0);
for(i=0;i<40;i++)
{ scanf<("%s",s);
fputs(s,fp);
fputc('\n',fp);
}
fclose(fp);
}
14 编程序完成下列要求:从键盘上输入某个姓名(字符串,长度<=20),在上一题(第13题)中建立的名为“sname.txt”的文本文件中查找,找到则输出“yes!”,找不到则输出 “no!”。
【说明】 因为建立的sname文本文件中的字符串是含有回车换行符的,所以进行查找时的姓名字符串也需要插入一个回车换行符。
【分析】 定义文件型指针,并且打开名为“sname.txt”文本文件,用于只读操作。输入待查的字符串,插入回车换行符。设置标记变量值为0,表示没有查到。再设计一个当型循环结构,控制循环的条件是“不是文件尾”;在循环体中,从文件中读取一个字符串,和待查字符串比较。两个字符串相等,则置标记变量为1(表示查到),并且强迫退出循环;两个字符串不相等,则继续循环。退出循环后,按照标记变量的值进行输出。
【答案】 #include"stdio.h"
#Include"string.h"
main()
{ FILE *fp;
char name[22],s[22];
int flag,i;
if((fp=fopen("sname.txt","r"))==NULL) exit(0);
scanf("%s",name);
for(i=0;name[i]!='\0';i++);/*找到字符串结束标记*/
name[i]='\n';/*字符串中插入一个回车换行符*/
name[i+1]='\0';/*补充一个字符串结束标记*/
flag= 0;
while(!feof(fp))
{ fgets(s,21,fp);
if(strcmp(s,name)==0)
{ flag=1;
break;
}
}
if(flag==1)
printf("yes!\n");
else
printf("no!\n");
fclose(fp);
}
15 按照下列要求,编写一个函数。
函数名: file_err
参数:fpp,一个文件型指针
功能:测试fpp所指向的文件最近一次操作是否出现错误。
返回值:如果出现错误,则返回1;没有出现错误,则返回0。
【分析】在函数体中利用系统函数 ferroe()来测试参数“fpp”所指向的文件最近一次操作是否出错,依据ferror()函数的返回值(有错返回非0值。无错返回0值)来获得本函数的返回值进行返回。
【答案】 int file_err(fpp)
FILE *fpp;
{ int k;
k=ferror(fpp);
if(k)
return(1);
else
return(0);
}