12.3 文件的读、写
考点3 fputc()函数和fgetc()函数
真考链接
考点3较简单,属于重点理解内容。在选择题中,考核概率为10%。在操作题中考核概率为5%。
1. 调用fput函数输出一个字符
putc(或fputc)函数的调用形式如下:
putc(ch,fp);
其中,ch是待输出的某个字符,它可以是一个字符常量,也允许是一个字符变量;fp是文件指针。putc(ch,fp)的功能是将字符ch写到文件指针fp所指的文件中去。当输出成功,putc函数返回所输出的字符;如果输出失败,则返回一个EOF值。EOF是在stdio.h库函数文件中定义的符号常量,其值等于-1。
fputc函数的调用形式和函数的功能与putc函数完全一样。
2. 调用fgetc函数输入一个字符
getc函数的调用形式如下:
ch=getc(pf);
其中pf是文件指针。函数的功能是从pf指定的文件中读入一个字符,并把它作为函数值返回。ch=getc(pf)的功能是把从文件中读入的一个字符赋给变量ch。
fgetc函数的调用形式和函数的功能与getc函数完全相同。
真题精选
【例1】以下程序用于把从终端输入的字符输出到名为abc.txt的文件中,直到从终端读入字符#号时结束输入和输出操作,但程序有错。
#include<stdio.h>
main()
{ FILE *fout;char ch;
fout=fopen('abc.txt', 'w');
ch=fgetc(stdin);
while(ch!= '#')
{ fputc(ch,fout);
ch=fgetc(stdin);
}
fclose(fout);
}
出错的原因是( )。
A.函数fopen()调用形式错误 B.输入文件没有关闭
C.函数fgetc()调用形式错误 D.文件指针stdin没有定义
【答案】A
【解析】本题没有什么复杂的算法,主要考查基本语法,本题函数fopen()调用形式有错误。
【例2】以下程序用来统计文件中字符的个数。请填空。
#include <stdio.h>
main()
{ FILE *fp;long num=0;
if((fp=fopen("fname.dat"______))==NULL)
printf("Open error \n ");exit(0);
while ______
{ ______;
num++;
}
printf("num=% ld \n ",--num);
fclose(fp);
}
【答案】"r" (!feof(fp)) fgetc(fp)
【解析】按题目要求,程序要从文件中输入字符,因此在第一个空处应填“r”。程序使文件指针fp指向输入文件,因此在while后面应填(!feof(fp))。从文件中输入字符应该调用fgetc()函数,因为只是统计文件中字符的个数,而没有对输入的字符进行处理,所以在第三个空处应填fgetc(fp)。
【例3】以下C程序将磁盘中的一个文件复制到另一个文件中,两个文件名在命令行中给出(假定文件名无误)。请填空。
#include <stdio.h>
main(int argc,char *argv[ ])
{ FILE *f1,*f2;char ch;
if(argc<______)
{printf("命令行参数错!\n");exit(0);}
f1=fopen(argv[1],"r");
f2=fopen(argv[2],"w");
while(______)fputc(fgetc(f1),______);
______;
______;
}
【答案】3 !feof(f1) f2 fclose(f1) fclose(f2)
【解析】(1)因为要把一个文件复制到另一个文件中,因此需要打开两个文件。从程序来看,从中读取数据的文件名是放在argv[1]中的,并由文件指针f1指向;进行写操作的文件名是放在argv[2]中,并由文件指针f2指向。所以在命令行中至少要有3个字符串,第一个是本程序的执行文件名;第二个是输入文件名,第三个是输出文件名;字符串的个数放在main()函数的第一参数中,在此是argc中,因此argc的值不能小于3,所以在第一个空处应填3。
(2)读操作和写操作是同时在while循环中完成的。当f1所指文件遇到文件结束标识时,应退出循环,所以在第二个空处填!feof(f1),因为文件未结束时函数feof(f1)的值为0,因此应该在其前面加求反运算符“!”,使文件未结束时循环继续。
(3)fgetc(f1)函数是从f1所指文件中读取一个字符,并作为函数值返回。函数fputc(c,fp);是把c中的字符输出到fp所指的文件中。目前,在fputc(fgetc(f1),______)中,字符直接由函数fgetc(f1)从文件中得到,所以,在第三个空处应填输出文件指针f2。
(4)当退出程序时应当关闭已打开的文件,因此在第四和第五空处应填fclose(f1)和fclose(f2)。注意:不要忽略文件关闭操作,此操作将把输入和输出缓冲区(在内存)中的数据继续处理完毕,然后才使文件指针与文件脱离关系,否则将会丢失应当处理的数据。
【例4】下列给定程序的功能是:调用函数fun()将指定源文件中的内容复制到指定的目标文件中,复制成功时函数返回1,失败时返回0。在复制的过程中,把复制的内容输出到屏幕。主函数中源文件名放在变量sfname中,目标文件名放在变量tfname中。
请在标号处填入正确的内容,使程序得出正确的结果。
注意:部分源程序给出如下。不得增行或删行,也不得更改程序的结构。
试题程序
#include <stdio.h>
#include <stdlib.h>
int fun(char *source,char *target)
{ FILE *fs,*ft;char ch;
if((fs =fopen(source,【1】))==NULL) return 0;
if((ft=fopen(target,"w"))==NULL) return 0;
printf("\nThe data in file:\n");
ch=fgetc(fs);
while(!feof(【2】))
{ putchar(ch);
fputc(ch,【3】);
ch=fgetc(fs);
}
fclose(fs);fclose(ft);
printf("\n\n");
return 1;
}
main()
{ char sfname[20] ="myfile1",tfname
[20] ="myfile2";
FILE *myf;int i;char c;
myf=fopen(sfname,"w");
printf("\nThe original data:\n");
for(i=1;i<30;i++)
{ 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!");
}
【答案】【1】"r" 【2】source 【3】target
【解析】标号【1】:填"r"表示人source读出文件。
标号【2】:判断source文件是否读完。
标号【3】:向目标文件写内容。
考点4 fread()函数和fwrite()函数
真考链接
考点4难度适中,属于重点掌握内容。在选择题中考核概率为30%。在操作题中,主要在修改题中进行考查,考核概率为10%。
当要求一次性读写一组数据时,如一个实数或一个结构体变量的值,就可以使用fread()函数和fwrite()函数,它们的一般调用形式为:
fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
其中,buffer代表的是一个指针;size代表的是要读写的字节数;count用来指定每读写一次,输入或输出数据块的个数(每个数据块具有 size个字节);fp是文件类型指针。
真题精选
有以下程序:
#include<stdio.h>
main()
{ FILE *pf;
char *s1 = "China",*s2 = "Beijing";
pf = fopen("abc.dat","wb+");
fwrite(s2,7,1,pf);
fwrite(s1,3,1,pf);
fclose(pf);
}
以上程序运行后,abc.dat文件的内容是( )。
A.China B.Beijing C.BeijingChi D.BeijingChina
【答案】C
【解析】本题考查fread和fwrite函数的使用。fwrite(s2,7,1,pf);语句向文件写入字符串s2,fwrite(s1,3,1,pf);语句向文件写入s1的前3位,最终文件abc.dat的内容是BeijingChi。
考点5 fscanf()函数和fprintf()函数
真考链接
考点5 属于重点理解重点掌握内容,在选择题中考核概率为40%。在操作题中,主要放到编程题中,考核概率为10%。
fscanf()函数和 fprintf()函数都是格式化的读写函数,与 scanf()和printf()函数作用相似,但fscanf()函数和fprintf()函数读写对象是磁盘文件上的数据。它们的一般形式如下:
fscanf(文件指针,格式字符串,输入列表);
fprintf(文件指针,格式字符串,输出列表);
真题精选
【例1】下列程序的输出结果是( )。
#include<stdio.h>
main()
{ FILE *fp;int i,k=0,n=0;
fp=fopen("d1.dat","w");
for(i=1;i<4;i++)fprintf(fp,"% d",i);
fclose(fp);
fp=fopen("d1.dat","r");
fscanf(fp,"% d% d",&k,&n);
printf("% d% d\n",k,n);
fclose(fp);
}
A.12 B.1230 C.123 D.00
【答案】B
【解析】fscanf从磁盘上读取ASCⅡ字符,给k和n赋值。在进行fp=fopen("dl.dat","w")操作时,向文件写字符,由fprintf()将1,2,3写入磁盘,再由磁盘符123传给k,且将0传给n。在文件写操作时,两个数之间应用空格隔开,而在本题中,没有用空格隔开,所以123视为一个数。
【例2】有以下程序:
#include<stdio.h>
main()
{ FILE*fp;int i=20,j=50,k,n;
fp=fopen("d1.dat","w");
fprintf(fp,"% d\n",i);
fprintf(fp,"% d\n",j);
fclose(fp);
fp=fopen("d1.dat","r");
fscanf(fp,"% d% d",&k,&n);
printf("% d % d\n",k,n);
fclose(fp);
}
程序运行后的输出结果是( )。
A.20 30 B.20 50 C.30 50 D.30 20
【答案】B
【解析】本题首先通过函数fprintf()将变量i、j的值输出到已打开的d1.dat文件中,再由函数fscanf()从d1.dat中读取i、j的值到k、n。
【例3】下列给定程序中,函数fun()的功能是:对N名学生的学习成绩,按从高到低的顺序找出前m(m≤10)名学生来,并将这些学生数据存放在一个动态分配的连续存储区中,此存储区的首地址作为函数值返回。
请改正程序中的错误,使它能得出正确的结果。
注意:不要改动main()函数,不得增行或删行,也不得更改程序的结构。
试题程序
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#define N 10
typedef struct ss
{ char num[10];
int s;
}STU;
STU *fun(STU a[ ],int m)
{ STU b[N],*t;
int i,j,k;
/*****found*****/
*t=calloc(m,sizeof(STU));
for(i=0;i<N;i++)
b[i] =a[i];
for(k=0;k<m;k++)
{ for(i=j=0;i<N;i++)
if(b[i].s>b[j].s)
j=i;
/*****found*****/
t[k].num=b[j].num;
t[k].s=b[j].s;
b[j].s=0;
}
return t;
}
outresult(STU a[ ],FILE *pf)
{ int i;
for(i=0;i<N;i++)
fprintf(pf,"No =% s Mark =% d\n ",a [i].num,a[i].s);
fprintf(pf,"\n\n ");
}
void main()
{ STU a[N] ={{"A01 ",81},{"A02 ",89},
{"A03 ",66},{"A04 ",87},{"A05 ",77},
{"A06 ",90},{"A07 ",79},{"A08 ",61},
{"A09 ",80},{"A10 ",71}};
STU *pOrder;
int i,m;
printf("****THE RESULT****\n");
outresult(a,stdout);
printf(" \nGive the number of the students who have better score:");
scanf("% d",&m);
while(m>10)
{ printf("\ nGive the number of the
students who have better score:");
scanf("% d",&m);
}
pOrder=fun(a,m);
printf("**** THE RESULT****\n");
printf("The top:\n");
for(i=0;i<m;i++)
printf("% s % d\n",pOrder[i].num, pOrder[i].s);
free(pOrder);
}
【答案】(1)t=calloc(m,sizeof(STU)); (2)t[k] =b[j];
【解析】calloc应用于分配内存空间。调用形式为(类型说明符*)calloc(n,size),功能:在内存动态存储区中分配n块长度为“size”字节的连续区域,函数的返回值为该区域的首地址,(类型说明符*)用于强制类型转换。calloc函数与malloc函数的区别在于calloc函数一次可以分配n块区域。例如,ps=(structstu*)calloc(2,sizeof(structstu));,其中的sizeof(structstu)是求stu的结构长度。因此该语句的意思是:按stu的长度分配两块连续区域,强制转换为stu类型,并把其首地址赋予指针变量ps。在本例中不用考虑那么复杂,根据定义类型STUb[N],*t,就可以看出*t=calloc(m,sizeof(STU))中的错误。t[k].num=b[j].num的错误旨在考查对结构体概念的掌握和灵活应用程度。
考点6 fgets()函数和fputs()函数
真考链接
考点6较简单,属于重点理解内容。在选择题中考核概率为20%。在操作题中,主要在改错题中出现,考核概率为5%。
1. fgets函数
fgets函数用来从文件中读入字符串。fgets函数的调用形式如下:
fgets(str,n,fp);
其中,fp是文件指针;str是存放字符串的起始地址;n是一个int类型变量。函数的功能是从fp所指文件中读入n-1个字符放入以str为起始地址的空间内。如果在未读完n-1个字符时,已经读到一个换行符或一个EOF (文件结束标识),则结束本次读操作,读入的字符串中最后包含读到的换行符。因此,确切地说,调用fgets函数时,最多只能读入n-1个字符。读入结束后,系统将自动在最后加'\0',并以str作为函数值返回。
2. fputs函数
fputs函数用来把字符串输出到文件中。fputs函数的调用形式如下:
fputs(str,fp);
其中,fp是文件指针;str是待输出的字符串,可以是字符串常量、指向字符串的指针或存放字符串的字符数组名等。用此函数进行输出时,字符串中最后的'\0'并不输出,也不自动加“\n”。输出成功,则函数值为正整数,否则为-1(EOF)。
常见问题
调用fputs函数输出字符串时应注意什么问题?
根据fputs函数的操作特点,在调用函数输出字符串时,文件中各字符串将首尾相接,它们之间将不存在任何间隔符。为了便于读入,在输出字符串时,应当注意人为地加入诸如“\n”这样的字符串。
真题精选
【例1】标准函数fgets(s,n,f)的功能是( )。
A.从f所指的文件中读取长度为n的字符串存入指针s所指的内存
B.从f所指的文件中读取长度不超过n-1的字符串存入指针s所指的内存
C.从f所指的文件中读取n个字符串存入指针s所指的内存
D.从f所指的文件中读取长度为n-1的字符串存入指针s所指的内存
【答案】B
【解析】fgets(s,n,f)函数的功能是从f所指文件中读入n-1个字符放入以s为起始地址的空间内;如果未读满n-1个字符时已读到了一个换行符或EOF,则结束本次读入。因此确切地说,调用fgets()函数最多只能读入n-1个字符。
【例2】下列给定程序的功能是:从键盘输入若干行字符串(每行不超过80个字符),写入文件myfile4.txt中,用-1作字符串输入结束的标志,然后将文件的内容显示在屏幕上。文件的读写分别由函数ReadText和WriteText实现。
请在标号处填入正确的内容,使程序得出正确的结果。
注意:部分源程序给出如下。不得增行或删行,也不得更改程序的结构。
试题程序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void WriteText(FILE *);
void ReadText(FILE *);
main()
{ FILE *fp;
if((fp=fopen("myfile4.txt","w"))==NULL){ printf(" open fail!!\n");exit (0);}
WriteText(fp);
fclose(fp);
if((fp=fopen("myfile4.txt","r"))==NULL){ printf(" open fail!!\n");exit (0);}
ReadText(fp);
fclose(fp);
}
void WriteText(FILE【1】)
{ char str[81];
printf("\nEnter string with -1 to end:\n");
gets(str);
while(strcmp(str,"-1")!=0){
fputs(【2】,fw);fputs("\n",fw);
gets(str);
}
}
void ReadText(FILE *fr)
{ char str[81];
printf(" \nRead file and output to screen:\n");
fgets(str,81,fr);
while(!feof(fr)){
printf("% s",【3】);
fgets(str,81,fr);
}
}
【答案】【1】*fw 【2】str 【3】str
【解析】本题考查:函数定义及文件指针。fputs函数的功能是向指定的文件写入一个字符串,其调用形式为:fputs(字符串,文件指针)。
标号【1】:定义函数,函数的形参是一个文件类型的指针。
标号【2】:此处考查fputs函数的形式,应填入str。
标号【3】:依据printf函数的格式,输出字符串内容,即printf("%s",str)。