●试题四 阅读下列程序说明和C代码,将应填入(n)处的字句写在答题纸的对应栏内。 【说明】 本程序从若干个原始文件合并成的合并文件中恢复出其中一个或全部原始文件。所有文件均作为二进制文件进行处理。合并文件中先顺序存储各原始文件,然后顺序存储各原始文件的控制信息,即文件名、文件长度和在合并文件中的位置(偏移量 )。其结构为: typedef struct{char fname [256]/*原始文件名*/ long length;/*原始文件长度(字节数)*/ long offset;/*原始文件在合并文件中的位置(偏移量)*/ }FileInfo; 在合并文件最后存储如下一个特殊的标志信息作为合并文件的结束标记: FileInfo EndF1ag={'Combined File',0,_offset}; 其中_offset是第一个原始文件的控制信息在合并文件中的位置(偏移量)。 启动本程序的命令行的格式是: 程序名合并文件名[原始文件名] 如果不指定原始文件名,默认恢复合并文件中的所有原始文件。 程序中涉及的部分文件操作的库函数简要说明如下: int fread (void *buffer,int size,int count,FILE *fbin):从二进制文件流fbin中读取count块长度为size字节的数据块到buffer指向的存储区。返回值为实际读取的数据块数。 int fwrite(void *buffer,int size,int count,FILE *fbin):各参数和返回值的意义与fread相同,但对文件进行写操作。 int fseek(FILE *fbin,long offset,int position):将文件流fbin的读/写位置以position为基准移动offset字节。position的值可以是SEEK_SET(文件头),SEEK_CUR(当前位置),SEEK_END(文件尾);offset为正,表示向文件尾方向移动,为负表示向文件头方向移动,为零表示到基准位置。 long ftell(FILE *fbin):返回文件流fbin的当前读/写位置(相对于文件头的偏移量)。上述偏移量均以字节为单位,即偏移字节数。 【程序】 #include #include typedef struct{char fname[256];long length;long offset; }FileInfo; void copyfile(FILE *fin,FILE *fout,int fsize) {char buf[1024];int siz=1024; while(fsize !=0){/*每次复制siz个字节,直至复制完fsize个字节*/ if(siz >fsize) (1) ; fread(buf,1,siz,fin);fwrite(buf,1,siz,fout); fsize= (2) ;} } int dofile(FILE *fin,FileInfo *inp) { long offset; FILE *fout; if((fout=fopen(inp->fname,'wb'))==NULL){ printf('创建文件错误:%s\n',inp->fname); return 1; } offset= (3) ;/*保留合并文件读/写位置*/ fseek( (4) );/*定位于被恢复文件首*/ copyfile(fin,fout,inp->length); fclose(fout); printf('\n---文件名:%\n文件长:%1d. \n',inp->fname,inp->length); (5) ;/*恢复合并文件读/写位置*/ return 0; } int main(int argc,char *argv[]) {FileInfo finfo; char fname[256];FILE *fcmbn; if(argc<2){printf('输入合并文件名:');scanf('%s',fname);} else strcpy(fname,argv[1]); if((fcmbn=fopen(fname,'rb'))==NULL){ printf('文件打开错误:%s\n',fname);return 1; } fseek(fcmbn,-sizeof(FileInfo),SEEK_END);/*定位于合并文件末尾的标志信息*/ fread(&finfo,1,sizeof(FileInfo),fcmbn); if(finfo.length!=0 || strcmp(finfo.fnane,'CombinedFile')){ printf('指定的文件不是合法的合并文件\n'); fclose(fcmbn);return 2; } fseek(fcmbn,finfo.offset,SEEK_SET);/*定位于首个原始文件的控制信息*/ for(;;){/*恢复一个(argc>2)或全部(argc=2)原始文件*/ fread(&finfo,1,sizeof(FileInfo),fcmbn); if(finfo.length==0)break; if(argc>2 && strcmp(finfo.fname,argv[2]))continue; if(dofile(fcmbn,&finfo)!=0)break; } fcolse(fcmbn);return 0; }