加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

《C程序设计语言学习笔记23》合并输出文件内容&比较两个文件并打印他们第一个不同的行

(2014-09-16 18:58:41)
标签:

it

程序

分类: C语言学习
这是一个很值得去看的属于我自己的心得,从前些日子开始一直在进行C语言中的文件学习,并打算在后面收尾的时间里把前面的比较好的程序用调用文件的方式运行。
关于文件的访问主要有以下函数:
FILE *fopen(char *name,char *mode)函数
fopen的第一个参数是一个字符串,它包含的是文件名。第二个参数是访问模式,也是一个字符串,用于指定文件的使用方式,有如下一些方式和细节我们需要注意。
r以只读的方式打开文件(该文件必须存在,否则会报错)
r+以可读可写的方式打开文件(该文件必须存在,否则会报错)
rb+读写方式打开一个二进制文件(该文件必须存在,否则会报错) 
rw+读写方式打开一个二进制文件(该文件必须存在,否则会报错) 
w打开只写文件,若文件存在则文件的长度清0,即文件的内容消失,若文件不存在则创建该文件
w+打开可读写文件,若文件存在则文件长度清0,即文件的内容消失,若文件不存在则创建文件
a以追加的方式打开只写文件。若文件不存在,则会建立该文件,若原来的文件存在,写入的数据会被加到原来的数据后面,即原来的内容会被保留
a+以追加的方式打开可读写文件。若文件不存在,则会建立该文件,若原来的文件存在,写入的数据会被加到原来的数据后面,即原来的内容会被保留
wb只写打开或建立一个二进制文件,只允许写数据
wb+读写打开或建立一个二进制文件,允许读和写 
ab+读写打开一个二进制文件,允许读或在文件末尾追加数据
一般的用法是定义一个指向文件的指针FILE *fp;令fp=fopen(name,mode);
如果文件被成功打开则返回指向文件的指针,否则返回NULL。
int getc(FILE *fp)函数
getc函数从文件中返回下一个字符,它需要知道文件指针以确定对哪个文件执行操作,函数返回fp指向的输入流中的下一个字符。如果达到文件尾或出现错误,该函数将返回EOF。
int putc(int c,FILE *fp)函数
该函数将字符c写入到fp指向的文件中,并返回写入的字符。如果发生错误,则返回EOF。
int ungetc(int c,FILE *fp)函数
它的作用是将字符c写回到文件fp中。如果执行成功,则返回c否则返回EOF。没一个文件只能够接收一个写回字符。
int fscanf(FILE *fp,char *format,arg1,arg2...)和函数int fprintf(FILE *fp,char *format,arg1,arg2...)能够控制文件的输入与输出。
int fclose(FILE *fp)函数
执行与fopen相反的操作,它断开fopen函数建立的文件指针和外部名之间的连接,并释放文件指针以供其他的文件使用。
void exit(int status)函数
这个函数的作用是关闭所有的文件,终止正在执行的进程。除了exit(0)以外的所有的返回值都是表示异常的信息。在main函数里面,语句return expr等价于exit(expr)。
int ferror(FILE *fp)函数
如果流fp中出现错误,则函数ferror返回一个非0值。函数int feof(FILE *fp)和其实一致的。


下面是书上的一个函数,我照原样来看了一下它的实现。
对于这个函数,首先要说的是main函数是自带参数的,所以应该从DOS下调用。
这个函数实现的是将多个文件的内容共同输出在屏幕上面。对于没有文件的操作执行标准输入与输出的操作。
#include< stdio.h >
#include< stdlib.h >
void filecopy(FILE *,FILE *);

main(int argc,char *argv[]){
FILE *fp;
char *prog;
prog=argv[0];
printf("这是一个把多个文件的内容合并输出在屏幕上的小程序:\n");
if(argc==1)
filecopy(stdin,stdout);
//执行标准的输入与输出,意思就是说,如果只是调用这个函数的话,我们从键盘上输入什么样的字符,相应的屏幕上就会显示什么样的字符
else
while(--argc>0)
if((fp=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"%s:can not open %s\n",prog,*argv);
//将fprintf函数产生的诊断信息输出到stderr上,因此诊断信息将会显示在屏幕上。
exit(1);
}
else{
filecopy(fp,stdout);
fclose(fp);
}
if(ferror(stdout)){
//如果标准输出出现了错误,就显示该错误
fprintf(stderr,"错误的标准输出\n");
exit(2);
}
exit(0);
}

void filecopy(FILE *ifp,FILE *ofp){
int c;
while((c=getc(ifp))!=EOF){
putc(c,ofp);
}
}

下面是自己编写的练习7-6编写一个函数,比较两个文件并打印它们第一个不相同的行。而我的程序是实现了打印它里面不相同的所有行。
在讲我写的这个程序之前,我们先来看关于文件里面其他几个重要函数的作用和使用细节。
其中用到了一个非常实用的函数:
char *fgets(char *line,int maxline,FILE *fp)
fgets函数从fp指向文件中读取下一个输入行(包括换行符),并将它存放在字符数组line中,它最多可读取maxline-1个字符。读取的行将以'\0'结尾保存到数组中。通常情况下,fgets函数返回line,但遇到了文件结尾或发生了错误,则返回NULL。
int fputs(char *line,FILE *fp)
输出函数fputs将一个字符串(不需要包含换行符)写入到一个文件中。如果发生错误,该函数将返回EOF,否则将会返回一个非负值。
下面来看我自己编写的这个程序:
同样这个函数也是需要在DOS下执行的。
#include< stdio.h >
#include< stdlib.h >
#define MAXLINE 100

void filecmp(FILE *,FILE *);
void out(char *);//这个函数的定义是为了去掉每一行后面的\n字符,因为fgets这个函数是能够读取\n这个字符的,对完整不超过限定的一行,读取之后在后面加\0。

int main(int argc,char **argv){
FILE *fp1,*fp2;
if(argc!=3){
fprintf(stderr,"文件的个数非法\n");
exit(1);
}
if((fp1=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"第一个文件打不开!\n");
exit(1);
}else if((fp2=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"第二个文件打不开!\n");
exit(1);
}else{
filecmp(fp1,fp2);
fclose(fp1);
fclose(fp2);
exit(0);
}
}

void filecmp(FILE *fp1,FILE *fp2){
char line1[MAXLINE],line2[MAXLINE];
static char *s1,*s2;
int count=0;
int difcount=0;
do{
s1=fgets(line1,MAXLINE,fp1);
s2=fgets(line2,MAXLINE,fp2);
out(line1);//去换行符
out(line2);//去换行符
if(s1==line1 && s2==line2)
if(strcmp(line1,line2)!=0){
printf("第[%d]行出现了不同,分别是:\n第一个文件的%s\n第二个文件的%s\n",count+1,line1,line2);
difcount++;
}
if(s1!=line1 && s2==line2){
printf("第一个文件已经结束了!其中不同的行数为[%d]行,第一个文件一共有[%d]行.",difcount,count);
}
if(s1==line1 && s2!=line2){
printf("第二个文件已经结束了!其中不同的行数为[%d]行,第二个文件一共有[%d]行.",difcount,count);
}
count++;
}while(s1==line1 && s2==line2);
if(difcount==0)
printf("两个文件没有什么不同.");
if(s1==NULL && s2==NULL)
//这里说说为什么要使用这个来判别呢?  因为do-while这个程序会先执行一次,也就是输如果我两个文件的行数是一致的,那么他会超前执行这两句话s1=fgets(line1,MAXLINE,fp1);和s2=fgets(line2,MAXLINE,fp2);也就是说,我执行后如果两个文件同时结束的话,s1和s2都是指向空的。
printf("两个文件同时结束了,其中不同的行数为[%d]行,两个文件都有[%d]行.",difcount,count-1);
}

void out(char *line){
int length=strlen(line);
if(line[length-1]=='\n')
line[length-1]='\0';
}
//显然  我编写这个函数是很有必要的。就是根据fgets这个函数的特性。























0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有