C语言进阶-第35讲:标准文件读写方法(以字符/字符串复制文件引发的思考)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_39286218/article/details/78680853

任务和代码(一):

/*以字符为单位复制文件*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
    FILE *fp1,*fp2;
    char ch;
    if((fp1=fopen("a.txt","r"))==NULL)    /*打开用于复制的源文件*/
    {
        printf("Cannot open source file.\n");
        exit(1);
    }
    if((fp2=fopen("b.txt","w+"))==NULL)   /*打开用于写入的目标文件*/
    {
        printf("Cannot open traget file.\n");
        exit(1);
    }
    while((ch=fgetc(fp1))!=EOF)           /*从源文件中逐个地读出字符*/
        fputc(ch,fp2);                    /*将读出的字符逐个写入到文件*/
    fclose(fp1);
    fclose(fp2);
    return 0;
}

任务和代码(二):

/*以字符串为单位复制文件*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
    FILE *fp1,*fp2;
    char string[80];                        /*定义字符数组,用于读入字符串*/
    if((fp1=fopen("a.txt","r"))==NULL)      /*打开用于复制的源文件*/
    {
        printf("Cannot open source file.\n");
        exit(1);
    }
    if((fp2=fopen("b.txt","w+"))==NULL)     /*打开用于写入的目标文件*/
    {
        printf("Cannot open traget file.\n");
        exit(1);
    }
    fgets(string, 80, fp1);                 /*从源文件中读入字符串*/
    while(!feof(fp1))                       /*若未结束*/
    {
        fputs(string, fp2);                 /*将读入的字符串写入目标文件*/
        fgets(string, 80, fp1);             /*继续从源文件中读入字符串*/
    }
    fclose(fp1);
    fclose(fp2);
    return 0;
}
a.txt



Q&A:

Q1:代码(二)中,又见feof()函数,运行后,打开b.txt,少一行,为什么?怎么改?

A1:执行最后一条fgets()后,最后一行字符串被读到,但此时文件指针已指向文件末尾,退出循环

改进1,在循环体后加上输出语句fputs(string, fp2);

改进2,在a.txt文件末尾多一段空白行。


Q2:feof()与EOF结束符有什么区别?在代码(一)中能否用feof()实现?代码(二)呢?

A2:EOF,文件结束符,值为-1;feof()的函数原型 int feof(FILE *stream);文件结束返回1,否则为0

以字符为单位复制文件时,fgetc()的返回值是int(char也可以理解为int),而EOF的值为-1,就可以判断文件指针指向的字符是否到了文件结束位置;

将代码(一)中的循环体修改如下:

    ch=fgetc(fp1);
    while(!feof(fp1)){
        fputc(ch,fp2);
        ch=fgetc(fp1);
    }
而以字符串为单位复制文件时,fgets()的返回值是地址,与EOF的类型不匹配。
由此看出,feof()用于判断文件指针是否指向了文件结束,其使用要比用EOF结束符用于判断的范围广


Q3:能用fgetc()、fgets()读取文件指针,能不能换成fscanf()?若能,如何?

A3:首先介绍 fgetc() 、fgets() 、fscanf()是如何读取文本文件的

   scanf()/getchar()    //只有遇到回车会将回车读入缓存区并结束,当读入空格、\t 时不会结束
   scanf("%s",str);   //遇空格、\t、回车结束
   gets(str);              //遇空格、\t不结束, 遇回车结束
   fgetc()             //会读入每一个字符直到文件指针指向文件结束符
   fgets()            //只遇到换行符文件指针才移到下一字符串(按行读取)
   fscanf()          //遇到空格、\t和换行时文件指针指向下一字符串(读入格式化数据)

用fscanf()修改代码(二)试试:

    fscanf(fp1,"%s",string);
    while(!feof(fp1))   
    {
        fprintf(fp2,"%s",string);           
        fscanf(fp1,"%s",string);        
    }
其运行结果就是b.txt中出现连续的一整串字符,了解fscanf() 的读取方式后就明白,被空格、\t和换行符间隔的字符或字符串都作为字符串进行读取


Q4:fcanf()与fgers()/fread()读到文件末尾的区别?

A4:fscanf完最后一行,fp未指向文件末尾,继续读取循环语句,再次fscanf后,跳出循环

        fgets/fread完最后一行,fp1已指向文件末尾,下一步跳出循环,毫不含糊!

        因此在A1中,还可以这样做:

while(!feof(fp1)) {
    fgets(string, 80, fp1); 
    fputs(string, fp2);                 
}
注意,在使用while(!feof(fp))时,只有当扫描语句是fscanf时,才要将其放在循环体内其他语句之后。

Q5:还有没有其他方式可以替换feof()函数的使用?

A5:以字符串为单位复制文件为例,将代码(二)的循环体做以下修改:

一:以fgets()读取文件

while (fgets(string, 80, fp1) != NULL)  {  
    fputs(string, fp2);  
} 

二:以fscanf()读取文件

while (fscanf(fp1, "%s", string) == 1)  {  
    fprintf(fp2, "%s", string);  
}  





PS:

任务和代码(三):

/*使用非标准文件操作实现文件的复制功能*/
#include <stdio.h>
#include <fcntl.h>                              //包含非标准文件操作的头文件
#include <stdlib.h>
int main()
{
    int handle1, handle2;                       //文件号,读写文件时和文件相联系(而非FILE *fp)
    char ch, filename1[20], filename2[20];
    printf("enter source filename:");
    gets(filename1);
    if((handle1=open(filename1, O_RDONLY))==-1) //int型文件号,打开失败返回1
        exit(1);
    printf("enter destination filename:");
    gets(filename2);
    if((handle2=open(filename2, O_WRONLY))==-1)
        exit(1);
    while(read(handle1, &ch, 1)>0)              //从文件号为handle1的文件中读一个字节的数据给内存变量ch,无读入数据,返回-1
        write(handle2, &ch, 1);                 //讲一个字节的字符变量i的值存入文件号为handle2的文件中
    puts("Success");
    close(handle1);
    close(handle2);
    return 0;
}

运行结果:





猜你喜欢

转载自blog.csdn.net/sinat_39286218/article/details/78680853