第6章 文件操作

6.1 文件读写操作

在C语言中,“文件”是一逻辑概念,可以用来表示从磁盘文件到终端等所有东西,本小节就来介绍对磁盘文件进行打开或读写操作的几种不同方法,在学习完这几种方法后再遇到类似问题,可根据不同情况选择不同的读写方式。

实例167 读取磁盘文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\167

实例说明

要求在程序执行前,在任意路径下新建一个文本文档,文档内容为hello world hello mingri!编程实现从键盘中输入文件路径及名称,在屏幕中显示出该文件内容。运行结果如图6.1所示。

图6.1 读取磁盘文件

技术要点

本实例用到了几个与文件操作相关的函数,下面就来逐一介绍。

● fopen文件的打开函数

        FILE *fp
        fp=fopen(文件名,使用文件方式)

例如:

        fp=fopen("123.txt", r");

它表示要打开名称为123的文本文档,使用文件方式为“只读”,fopen函数带回指向123.txt文件的指针并赋给fp,也就是说fp指向123.txt文件。

使用文件方式如表6.1所示。

表6.1 文件使用方式及含义

● fclose文件的关闭函数

        fclose(文件指针)

作用是通过文件指针将该文件关闭。

● fgetc函数

        ch=fgetc(fp);

该函数作用是从指定的文件(fp指向的文件)读入一个字符赋给ch。注意该文件必须是以读或读写方式打开。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)用while循环实现字符的输出。

(4)main()函数作为程序的入口函数,代码如下:

        main()
        {
            FILE*fp;                          /*定义一个指向FILE类型结构体的指针变量*/
            char ch,filename[50];             /*定义变量及数组为字符型*/
            printf("please input file`s name;\n");
            gets(filename);                 /*输入文件所在路径及名称*/
            fp=fopen(filename,"r");         /*以只读方式打开指定文件*/
            ch=fgetc(fp);                   /*fgetc函数带回一个字符赋给ch*/
            while(ch!=EOF)                 /*当读入的字符值等于EOF时结束循环*/
            {
              putchar(ch);                  /*将读入的字符输出在屏幕上*/
              ch=fgetc(fp);                 /*fgetc函数继续带回一个字符赋给ch*/
            }
            fclose(fp);                     /*关闭文件*/
        }

举一反三

根据本实例,读者可以:

要求读取当前目录下一个已经存在的二进制文件的内容。

要求读取当前目录下一个已经存在的文本文档内容。

实例168 将数据写入磁盘文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\168

实例说明

编程实现将数据写入磁盘文件,即在任意路径下新建一个文本文档,向该文档中写入mingri tu shu,nin shen bian de liang shi yi you!,以“#“结束字符串的输入。运行结果如图6.2所示。

图6.2 读取磁盘文件

技术要点

本实例中用到了fputc函数,具体函数使用说明如下。

● fputc函数

        ch=fputc(ch,fp);

该函数作用是把一个字符写到磁盘文件(fp所指向的是文件)上去。其中ch是要输出的字符,它可以是一个字符常量,也可以是一个字符变量。fp是文件指针变量。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)用while循环来实现字符的读入。

(4)main()函数作为程序的入口函数,代码如下:

        main()
        {
            FILE*fp;                                 /*定义一个指向FILE类型结构体的指针变量*/
            char ch,filename[50];                    /*定义变量及数组为字符型*/
            printf("please input filename:\n");
            scanf("%s",filename);                  /*输入文件所在路径及名称*/
            if((fp=fopen(filename,"w"))==NULL)/*以只写方式打开指定文件*/
            {
                printf("cannot open file\n");
                exit(0);
            }
            ch=getchar();                          /*fgetc函数带回一个字符赋给ch*/
            while(ch!='#')                        /*当输入"#"时结束循环*/
            {
                fputc(ch,fp);                      /*将读入的字符写到磁盘文件上去*/
                ch=getchar();                      /*fgetc函数继续带回一个字符赋给ch*/
            }
            fclose(fp);                            /*关闭文件*/
        }

举一反三

根据本实例,读者可以:

要求在当前目录下新建一个文本文档,写入该文档的内容为“hello”。

要求在F根目录下新建一个二进制文件,写入该文档的内容为“Morning”。

实例169 格式化读写文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\169

实例说明

编程实现将输入的小写字母串写入磁盘文件,再将刚写入磁盘文件的内容读出并以大写字母的形式显示在屏幕上。运行结果如图6.3所示。

图6.3 读取磁盘文件

技术要点

本实例中用到了fprintf函数及fscanf函数,具体函数使用说明如下。

● fprintf函数

        ch=fprintf(文件指针,格式字符串,输出列表);

例如:

        fprintf(fp, "%d",i);

它的作用是将整型变量i的值按%d的格式输出到fp指向的文件上。

● fscanf函数

        fscanf(文件指针,格式字符串,输入列表)

例如:

        fscanf(fp, "%d",&i);

它的作用是读入fp所指向的文件上的i的值。

注意:fprintf和fscanf函数的读写对象不是终端而是磁盘文件。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)用while循环来实现字符串的读入,通过设置的标志位来判断是否结束字符串读入,当flag为1时继续读入字符串,当flag为0时停止读入字符串。

(4)实现将读入的小写字母转换为大写字母,只需将读入的小写的母的ASCII减32即可实现。

(5)main()函数作为程序的入口函数,代码如下:

        main()
        {
            int i,flag=1;                                    /*定义变量为基本整型*/
            char str[80],filename[50];                       /*定义数组为字符型*/
            FILE*fp;                                         /*定义一个指向FILE类型结构体的指针变量*/
            printf("please input filename:\n");
            scanf("%s",filename);                          /*输入文件所在路径及名称*/
            if((fp=fopen(filename,"w"))==NULL)        /*以只写方式打开指定文件*/
            {
              printf("cannot open!");
              exit(0);
            }
            while(flag = = 1)
            {
              printf("\nInput string:\n");
              scanf("%s",str);                             /*输入字符串*/
              fprintf(fp,"%s",str);                        /*将str字符串内容以%s形式写到fp所指文件上*/
              printf("\nContinue:?");
              if((getchar()=='N')||(getchar()=='n'))/*输入n结束输入*/
                    flag=0;                                  /*标志位置0*/
            }
            fclose(fp);                                    /*关闭文件*/
            fp=fopen(filename,"r");                        /*以只写读方式打开指定文件*/
            while(fscanf(fp,"%s",str)!=EOF)             /*从fp所指的文件中以%s形式读入字符串*/
            {
              for(i = 0; str[i] != '\0'; i++)
                    if((str[i] >= 'a')&&(str[i] <= 'z'))
                    str[i]-=32;                             /*将小写字母转换为小写字母*/
              printf("\n%s\n",str);                       /*输出转换后的字符串*/
            }
            fclose(fp);                                   /*关闭文件*/
        }

举一反三

根据本实例,读者可以:

要求使用格式化写入函数向F根目录下已建好的文本文件中写入字符串“happy happy”。

要求使用格式化读出函数将F根目录下的文本文件内容读出。

实例170 成块读写操作

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\170

实例说明

编程实现学生成绩信息统计,从键盘中输入学生成绩信息,保存到指定磁盘文件中,输入完全部信息后将磁盘文件中保存的信息输出到屏幕上。运行结果如图6.4所示。

图6.4 成块读写操作

技术要点

本实例中用到了fwrite函数及fread函数,具体函数使用说明如下。

● fwrite函数

        fwrite(buffer,size,count,fp);

它的作用是将buffer地址开始的信息,输出count次,每次写size字节到fp所指的文件中。

参数说明。

buffer:一个指针。要输出数据的地址(起始地址)。

size:要读写的字节数。

count:要进行读写多少个size字节的数据项。

fp:文件型指针。

● fread函数

        fread(buffer,size,count,fp)

它的作用是从fp所指的文件中读入count次,每次读size字节,读入的信息存在buffer地址中。

参数说明同fwrite函数,惟一不同是buffer是读入数据的存放地址。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)定义结构体类型数组,代码如下:

        struct student_score                                        /*定义结构体存储学生成绩信息*/
        {
            char name[10];
            int num;
            int China;
            int Math;
            int English;
        } score[100];

(4)自定义save()函数,作用是将输入的一组数据输出到指定的磁盘文件中去。代码如下:

        void save(char*name,int n)                                        /*自定义函数save*/
        {
            FILE*fp;                                                         /*定义一个指向FILE类型结构体的指针变量*/
            int i;
            if((fp=fopen(name,"wb"))==NULL)                            /*以只写方式打开指定文件*/
            {
              printf("cannot open file\n");
              exit(0);
            }
            for(i = 0; i < n; i++)
              if(fwrite(&score[i],sizeof(struct student_score),1,fp)!=1)/*将一组数据输出到fp所指的文件中*/
                    printf("file write error\n");                           /*如果写入文件不成功,则输出错误*/
            fclose(fp);                                                     /*关闭文件*/
        }

(5)自定义show()函数,作用是将从指定的文件中读入的一组输出显示到屏幕上。代码如下:

        void show(char*name,int n)                                 /*自定义函数show*/
        {
            int i;
            FILE*fp;                                                  /*定义一个指向FILE类型结构体的指针变量*/
            if((fp=fopen(name,"rb"))==NULL)                    /*以只读方式打开指定文件*/
            {
              printf("cannot open file\n");
              exit(0);
            } for(i = 0; i < n; i++)
            {
              fread(&score[i],sizeof(struct student_score),1,fp);/*从fp所指向的文件读入数据存到数组score中*/
              printf("%-10s%4d%4d%4d%4d\n", score[i].name, score[i].num,
                    score[i].China, score[i].Math, score[i].English);
            }
            fclose(fp);                                            /*以只写方式打开指定文件*/
        }

(6)main()函数作为程序的入口函数,代码如下:

        main()
        {
            int i,n;                                               /*变量类型为基本整型*/
            char filename[50];                                     /*数组为字符型*/
            printf("how many students in your class?\n");
            scanf("%d",&n);                                      /*输入学生数*/
            printf("please input filename:\n");
            scanf("%s",filename);                                /*输入文件所在路径及名称*/
            printf("please input name,number,China,math,English:\n");
            for(i=0;i<n;i++)                                    /*输入学生成绩信息*/
            {
              printf("NO%d", i + 1);
              scanf("%s%d%d%d%d", score[i].name, &score[i].num, &score[i].China,
                    &score[i].Math, &score[i].English);
              save(filename,n);                                  /*调用函数save*/
            }show(filename,n);                                   /*调用函数show*/
        }

举一反三

根据本实例,读者可以:

从键盘中输入公司职工信息(姓名、年龄、工资),保存到指定磁盘文件中。

从指定磁盘文件中读取公司职工信息(姓名、年龄、工资),并读取出的信息输出到屏幕上。

实例171 随机读写文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\171

实例说明

输入若干个学生信息,保存到指定磁盘文件中,要求将奇数条学生信息从磁盘中读入并显示在屏幕上。运行结果如图6.5所示。

图6.5 随机读写文件

技术要点

本实例中用到了fseek函数,具体函数使用说明如下。

● fseek函数

        fseek(文件类型指针,位移量,起始点);

它的作用是用来移动文件内部位置指针”,其中参数“起始点”表示从何处开始计算位移量。规定的起始点有3种:文件首、文件当前位置和文件尾。其表示方法如表6.2所示。

表6.2 起始点表示法

例如:

        fseek(fp,-20L,1);

表示将位置指针从当前位置向后退20字节。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)定义结构体类型数组,代码如下:

        struct student_type                                        /*定义结构体存储学生信息*/
        {
            char name[10];
            int num;
            int age;
        }stud[10];

(4)自定义save()函数,作用是将输入的一组数据输出到指定的磁盘文件中去。代码如下:

        void save(char*name,int n)                                         /*自定义函数save*/
        {
            FILE *fp;
            int i;
            if((fp=fopen(name,"wb"))==NULL)                            /*以只写方式打开指定文件*/
            {
                printf("cannot open file\n");
                exit(0);
            }
            for(i = 0; i < n; i++)
                if(fwrite(&stud[i],sizeof(struct student_type),1,fp)!=1)/*将一组数据输出到fp所指的文件中*/
                    printf("file write error\n");                           /*如果写入文件不成功,则输出错误*/
            fclose(fp);                                                     /*关闭文件*/
        }

(5)main()函数作为程序的入口函数,代码如下:

        main()
        {
            int i,n;                                           /*变量类型为基本整型*/
            FILE*fp;                                           /*定义一个指向FILE类型结构体的指针变量*/
            char filename[50];                                 /*数组为字符型*/
            printf("please input filename:\n");
            scanf("%s",filename);                            /*输入文件所在路径及名称*/
                        printf("please input the number of students:\n");
            scanf("%d",&n);                                  /*输入学生数*/
            printf("please input name,number,age:\n");
            for(i=0;i<n;i++)                                /*输入学生信息*/
            {
              printf("NO%d", i + 1);
              scanf("%s%d%d", stud[i].name, &stud[i].num, &stud[i].age);
              save(filename,n);                              /*调用函数save*/
            }if((fp=fopen(filename,"rb"))==NULL)        /*以只读方式打开指定文件*/
            {
              printf("can not open file\n");
              exit(0);
            }
            for(i = 0; i < n; i += 2)
            {
              fseek(fp,i*sizeof(struct student_type),0);   /*随着i的变化从文件开始处随机读文件*/
              fread(&stud[i],sizeof(struct student_type),1,fp);/*从fp所指向的文件读入数据存到数组stud中*/
              printf("%-10s%5d%5d\n", stud[i].name, stud[i].num, stud[i].age);
            }
            fclose(fp);                                      /*关闭文件*/
        }

举一反三

根据本实例,读者可以:

从键盘中输入公司职工信息(姓名、年龄、工资),保存到指定磁盘文件中,读取该信息中奇数条的信息。

从键盘中输入公司职工信息(姓名、年龄、工资),保存到指定磁盘文件中,读取该信息中偶数条的信息。

实例172 以行为单位读写文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\172

实例说明

从键盘中输入字符串“hello world hello mingri”,使用fputs函数将字符串内容输出到磁盘文件中,使用fgets函数从磁盘文件中读取字符串到数组s中,最终将其输出在屏幕上。运行结果如图6.6所示。

图6.6 随机读写文件

技术要点

本实例中用到了fputs和fgets函数,具体函数使用说明如下。

● fputs函数

        fputs(字符串,文件指针)

该函数的作用是向指定的文件写入一个字符串,其中字符串可以是字符串常量,也可以是字符数组名、指针或变量。

● fgets函数

        fgets(字符数组名,n,文件指针);

该函数的作用是从指定的文件中读一个字符串到字符数组中。n表示所得到的字符串中字符的个数(包含“\0”)。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)使用gets函数将获得的字符串存到数组str中,使用fputs函数将字符串存到fp所指向的文件中,使用fgets函数从fp所指向的文件中读入字符串存到数组s中。最终使用printf函数将字符数组s中的字符串输出。

(4)主要程序代码如下:

        main()
        {
            FILE*fp;                                 /*定义一个指向FILE类型结构体的指针变量*/
            char str[100],s[100],filename[50];       /*定义数组为字符型*/
            printf("please input string!\n");
            gets(str);                             /*获得字符串*/
            printf("please input filename:\n");
            scanf("%s",filename);                  /*输入文件所在路径及名称*/
            if((fp = fopen(filename, "wb"))!= NULL)
                                                     /*以只写方式打开指定文件*/
            {
                fputs(str,fp);                     /*把字符数组str中的字符串输出到fp指向的文件*/
                fclose(fp);
            }
            else
            {
                printf("cannot open!");
                exit(0);
            }
            if((fp = fopen(filename, "rb"))!= NULL)
            {
                while(fgets(s, sizeof(s), fp))
                                                    /*从fp所指的文件中读入字符串存入s中*/
                    printf("%s", s);
                                                    /*将字符串输出*/
                fclose(fp);                       /*关闭文件*/
            }
        }

举一反三

根据本实例,读者可以:

从键盘中输入字符串“good morning”,使用fputs函数将字符串内容输出到指定的磁盘文件中。

使用fgets函数从F根目录下已提前写好内容的磁盘文件中读取字符串。

6.2 文件内容操作

实际操作中可以对一个文件中的内容进行复制并粘贴到另一个文件中,如果用C来编写程序也同样可以实现该功能,而且还可实现程序错误检测等操作,本小节就介绍了几个有关文件内容的操作。

实例173 复制文件内容到另一文件

这是一个可以提高分析能力的实例

实例位置:光盘\mingrisoft\06\173

实例说明

编程实现将一个已存在的文本文档的内容复制到新建的文本文档中。运行结果如图6.7所示。

图6.7 随机读写文件

技术要点

本实例中实现复制的过程并不是很复杂,在写程序时要注意,在实现复制的过程中无论是复制的文件还是被复制的文件都应该是打开的状态,当复制完成后再将两个文件分别关闭。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)使用while循环从被复制的文件中逐个读取字符到另一个文件中。

(4)main()函数作为程序的入口函数,代码如下:

        main()
        {
            FILE*in,*out;                                   /*定义两个指向FILE类型结构体的指针变量*/
            char ch,infile[50],outfile[50];                 /*定义数组及变量为基本整型*/
            printf("Enter the infile name:\n");
            scanf("%s",infile);                           /*输入将要被复制的文件所在路径及名称*/
            printf("Enter the outfile name:\n");
            scanf("%s",outfile);                          /*输入新建的将用于复制的文件所在路径及名称*/
            if((in=fopen(infile,"r"))==NULL)         /*以只写方式打开指定文件*/
            {
              printf("cannot open infile\n");
              exit(0);
            }
            if((out = fopen(outfile, "w"))= = NULL)
            {
              printf("cannot open outfile\n");
              exit(0);
            }
            ch = fgetc(in);
            while(ch != EOF)
            {
              fputc(ch,out);                              /*将in指向的文件的内容复制到out所指向的文件中*/
              ch = fgetc(in);
            }
            fclose(in);
            fclose(out);
        }

举一反三

根据本实例,读者可以:

编程实现将F根目录下一个已建好的文本文档中的内容复制到D根目录下一个已经建好的还未写入任何内容的文本文档中。

编程实现将当前目录下一个已建好的文本文档中的内容复制到同目录下另一个文本文档中。

实例174 错误处理

这是一个可以提高分析能力的实例

实例位置:光盘\mingrisoft\06\174

实例说明

编程实现将文件中的制表符换成恰当数目的空格,要求每次读写操作后都调用ferror()函数检查错误。运行结果如图6.8所示。

图6.8 错误处理

技术要点

本实例中用到ferror()函数,具体使用说明如下:

        int ferror(FILE *stream)

该函数的作用是检测给定流里的文件错误。返回值为0时,表示没有出现错误,而非零值表示是有错。

与stream相关联的出错标记给出后,一直要保持到该文件被关闭,或调用了rewind()或者clearerr()为止。使用perror()函数可以确定该错误的确切性质。

该函数的原型在stdio.h中。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>
        #include <stdlib.h>

(3)自定义error()函数,作用是输出出错的性质,代码如下:

        void error(int e)                            /*自定义error函数判断出错的性质*/
        {
            if(e = = 0)
                printf("input error\n");
            else
                printf("output error\n");
            exit(1);                                  /* 跳出程序 */
        }

(4)main()函数作为程序的入口函数,代码如下:

        main()
        {
            FILE*in,  *out;                                 /*第一两个文件类型指针in和out*/
            int tab, i;
            char ch, filename1[30], filename2[30];
            printf("please input the filename1:");
            scanf("%s",filename1);                        /*输入文件路径及名称*/
            printf("please input the filename2:");
            scanf("%s",filename2);                        /*输入文件路径及名称*/
            if((in = fopen(filename1, "rb"))= = NULL)
            {
              printf("can not open the file %s。\n", filename1);
              exit(1);
            }
            if((out = fopen(filename2, "wb"))= = NULL)
            {
              printf("can not open the file %s。\n", filename2);
              exit(1);
            }
            tab = 0;
            ch=fgetc(in);                                 /*从指定的文件中读取字符*/
            while(!feof(in))
                                                            /*检测是否有读入错误*/
            {
              if(ferror(in))
                    error(0);
              if(ch = = '\t')
                                                            /*如果发现制表符,则输出相同数目的空格符*/
            {
                    for(i = tab; i < 8; i++)
                    {
                    putc(' ', out);
                    if(ferror(out))
                          error(1);
                    }
                    tab = 0;
            }
            else
            {
                    putc(ch, out);
                    if(ferror(out))
                                                            /*检查是否有输出错误*/
                      error(1);
                    tab++;
                    if(tab = = 8)
                    tab = 0;
                    if(ch = = '\n' || ch = = '\r')
                    tab = 0;
            }
            ch = fgetc(in);
          }
          fclose(in);
          fclose(out);
        }

举一反三

根据本实例,读者可以:

编程实现将文件中大写字母换成小写字母,要求每次读写操作后都调用ferror()函数检查错误。

编程实现将文件中的数字统一换成空格,要求每次读写操作后都调用ferror()函数检查错误。

实例175 合并两个文件信息

这是一个可以提高分析能力的实例

实例位置:光盘\mingrisoft\06\175

实例说明

有两个文本文档,第一个文本文档的内容是:“hello computer!!”,第二个文本文档的内容是:“This is a c program!!”,编程实现合并两个文件的信息,即将文档二的内容合并到文档一内容的后面。运行结果如图6.9所示。

图6.9 连接两个文件

技术要点

本实例中实现文件合并有一个技术要点需要强调一下:程序中有这样一句代码:

        fseek(fp2, 0L, 0);

为什么要加上这句代码呢?这是因为在前面的程序中实现了将文件二中的内容逐个读取并显示到屏幕上,当将文件二中的全部内容读取后位置指针fp2也就指到了文件末尾出,当在接下来的内容中我们想实现将文件二中的内容逐个合并到文件1中的时候,就必须将文件二中的位置指针fp2重新移到文件开始处。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)程序中三次使用while循环,前两次使用while循环是为了将两文件中原有内容显示在屏幕上,第三次使用while循环目的是将文件二中的内容逐个写入文件一中,从而实现合并。

(4)主要程序代码如下:

        main()
        {
            char ch,filename1[50],filename2[50];                 /*数组和变量的数据类型为字符型*/
            FILE*fp1,  *fp2;                                     /*定义两个指向FILE类型结构体的指针变量*/
            printf("please input filename1:\n");
            scanf("%s",filename1);                             /*输入文件所在路径及名称*/
            if((fp1=fopen(filename1,"a+"))==NULL)         /*以读写方式打开指定文件*/
            {
                printf(" cannot open\n");
                exit(0);
            }
            printf("file1:\n");
            ch = fgetc(fp1);
            while(ch != EOF)
            {
                putchar(ch);                                   /*将文件1中的内容输出*/
                ch = fgetc(fp1);
            }
            printf("\nplease input filename2:\n");
            scanf("%s",filename2);                             /*输入文件所在路径及名称*/
            if((fp2=fopen(filename2,"r"))==NULL)          /*以只读方式打开指定文件*/
            {
            printf("cannot open\n");
            exit(0);
            }
            printf("file2:\n");
            ch = fgetc(fp2);
            while(ch != EOF)
            {
            putchar(ch);                                       /*将文件2中的内容输出*/
            ch = fgetc(fp2);
            }
            fseek(fp2,0L,0);                                   /*将文件2中的位置指针移到文件开始处*/
            ch = fgetc(fp2);
            while(!feof(fp2))
            {
            fputc(ch,fp1);                                     /*将文件2中的内容输出到文件1中*/
            ch=fgetc(fp2);                                     /*继续读取文件2中的内容*/
            }
            fclose(fp1);                                       /*关闭文件1*/
            fclose(fp2);                                       /*关闭文件2*/
        }

举一反三

根据本实例,读者可以编程实现以下问题:

在当前目录下有两个二进制文件,将一个二进制文件中的内容合并到另一个二进制文件内容的后面。

在F根目录下的一个文本文件中的内容合并到该目录下的另一个文本文件内容的后面,并将合并后的内容显示在屏幕上。

实例176 统计文件内容

本实例是一个人性化的实例

实例位置:光盘\mingrisoft\06\176

实例说明

编程实现对指定文件中的内容进行统计。具体要求如下:输入要进行统计的文件的路径及名称,统计出该文件中字符、空格、数字及其他字符的个数,并将统计结果存到指定的磁盘文件中。运行结果如图6.10所示。

图6.10 统计文件内容

技术要点

像统计输入字符串中字符的个数这种程序大家可能已经不再陌生,很多练习题中都会出现这种程序,本题也是在这种题型的基础上延伸出来的且更有实用性。本程序中并没有太多难点,输入要进行统计的文件的路径及名称,统计的过程同以前做过的字符统计程序中的过程基本相同,主要是靠条件判断实现的,最后将统计结果存到指定的磁盘文件中即可。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)程序中使用while循环遍历要统计的文件中的每个字符,用条件判断语句对读入的字符进行判断并在相应的用于统计的变量数上加1。

(4)main()函数作为程序的入口函数,代码如下:

        main()
        {
            FILE*fp1,  *fp2;                                /*定义两个指向FILE类型结构体的指针变量*/
            char filename1[50],filename2[50],ch;            /*定义数组及变量为字符型*/
            long character,space,other,digit;               /*定义变量为长整形*/
            character=space=digit=other=0;                  /*长整形变量的初值均为0*/
            printf("Enter file name \n");
            scanf("%s",filename1);                        /*输入要进行统计的文件的路径及名称*/
            if((fp1 = fopen(filename1, "r"))= = NULL)
            /*以只读方式打开指定文件*/
            {
                printf("cannot open file\n");
                exit(1);
            }
            printf("Enter file name for write data:\n");
            scanf("%s",filename2);                        /*输入文件名即将统计结果放到那个文件中*/
            if((fp2=fopen(filename2,"w"))==NULL)     /*以可写方式要存放统计结果的文件*/
            {
                printf("cannot open file\n");
                exit(1);
            }
            while((ch=fgetc(fp1))!=EOF)              /*知道文件内容结束处停止while循环*/
                if(ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')
                    character++;                            /*当遇到字母时字符个数加1*/
            else if(ch = = ' ')
                space++;                                    /*当遇到空格时空格数加1*/
            else if(ch >= '0' && ch <= '9')
                digit++;                                    /*当遇到数字时数字数加1*/
            else
                other++;                                    /*当是其他字符时其他字符数加1*/
            close(fp1);                                   /*关闭fp1指向的文件*/
            fprintf(fp2, "character:%ld space:%ld digit:%ld other:%ld\n", character,
                space,digit,other);                        /*将统计结果写入fp指向的磁盘文件中*/
            fclose(fp2);                                  /*关闭fp2指向的文件*/
        }

举一反三

根据本实例,读者可以:

输入要进行统计的文件的路径及名称,统计出该文件中数字个数并将统计出的结果显示在屏幕上。

输入要进行统计的文件的路径及名称,统计出该文件中大写字母的个数并将统计出的结果存到该目录下的另一个文本文档中。

6.3 文件的创建、查找及删除

在日常操作中可以实现对文件的创建、查找和删除,同样这些操作通过用C编写的程序也能实现,本节介绍的几个实例就是有关这方面操作的。

实例177 创建文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\177

实例说明

编程实现文件的创建,具体要求如下:从键盘中输入要创建的文件所在的路径及名称,无论创建成功与否均输出提示信息。运行结果如图6.11所示。

图6.11 创建文件

技术要点

本实例在实现文件创建过程中使用了creat函数,具体使用说明如下。

● creat函数

        int creat(char *filename,int access);

该函数的作用是生成一个新文件,如果函数执行成功,返回一个句柄给文件,如果出错,函数返回-1,该函数在“io.h”头文件中。参数filename是任一有效文件名,参数access用来指定访问的模式和标明该文件为二进制文件还是文本文件。一般情况下,生成一个标准存档文件时access的值为0。access取值及含义如表6.3所示。

表6.3 access取值

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include<stdio.h>
        #include<io.h>

(3)调用函数creat实现文件的创建,主要程序代码如下:

        main()
        {
            int handle;
            char filename[50];                                     /*数组定义为字符类型*/
            printf("please input filename:\n");
            scanf("%s",filename);                                /*输入要创建的文件所在路径及名称*/
            if((handle=creatnew(filename,0))==  -1)
            {
              printf("\n Error!Cannot vreat!");                  /*如果文件创建失败,输出双引号中内容*/
            }
            else
            {
              printf("\nthis file has created!");                /*如果文件创建成功,输出双引号中内容*/
              close(handle);
            }
        }

举一反三

根据本实例,读者可以:

在D盘根目录下创建一个名为new的文本文档。

在当前目录下创建一个名为new的二进制文件。

实例178 创建临时文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\178

实例说明

编程实现临时文件的创建,要求将“hello world hello mingri”输出到临时文件之后,再读取临时文件上个内容并将其显示在屏幕上。运行结果如图6.12所示。

图6.12 创建临时文件

技术要点

本实例使用了tmpfile和rewind函数,具体使用说明如下。

● tmpfile函数

        FILE *tmpfile()

该函数的作用是创建一个临时文件。如果函数执行成功,它以读和写模式打开文件,返回一个文件指针。如果出错,返回NULL。

● rewind函数

        void rewind(FILE *fp)

该函数的作用是将文件的指针重新设置到该文件的起点。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include<stdio.h>

(3)调用tmpfile函数实现临时文件的创建,主要程序代码如下:

        main()
        {
            FILE*temp;                                         /*定义一个指向FILE类型结构体的指针变量*/
            char c;                                            /*定义变量c为字符型*/
            if((temp = tmpfile())!= NULL)
                fputs("\nhello world\nhello mingri",temp);   /*向临时文件中写入要求内容*/
            rewind(temp);                                    /*文件指针返回文件首*/
            while((c=fgetc(temp))!=EOF)                 /*读取临时文件中内容*/
                printf("%c",c);                              /*将读取的内容输出在屏幕上*/
            fclose(temp);                                    /*关闭临时文件*/
        }

举一反三

根据本实例,读者可以:

在当前目录下创建一个临时文件名。

利用creatnew函数创建新文件。

实例179 查找文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\179

实例说明

编程实现文件的查找,要求输入文件名,若该文件存在,则输出其路径,否则提示没有找到。运行结果如图6.13所示。

图6.13 查找文件

技术要点

本实例使用了searchpath函数,具体使用说明如下。

● searchpath函数

        char *searchpath(char *fname)

该函数的作用是找出由fname所指向的文件名。如果找到文件,返回指向全路径名的指针。如果文件没有找到,返回一个空指针,该函数原型在“dir.h”头文件中。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include<stdio.h>

(3)调用searchpath函数查找文件,主要程序代码如下:

        main()
        {
            char*ptr,filename[50];                                  /*定义变量及数组为字符型*/
            printf("please input the file name you want to search:\n");
            scanf("%s",filename);                                 /*输入要查找的文件名*/
            if((ptr = searchpath(filename))!= NULL)
              printf("the path is:%s\n",ptr);                     /*将文件所在的路径输出*/
            else
              printf("cannot find");                              /*若文件未找到,输出双引号内提示信息*/
        }

举一反三

根据本实例,读者可以:

查找当前目录中一个已存在的文件。

查找当前目录中一个不存在的文件。

实例180 重命名文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\180

实例说明

编程实现重命名文件,具体要求如下:从键盘中输入要重命名的文件的路径及名称,文件打开成功后输入新的路径及名称。运行结果如图6.14所示。

图6.14 重命名文件

技术要点

本实例使用了rename函数,具体使用说明如下。

● rename函数

        int rename(char *oldfname,char*newfname)

该函数的作用是把文件的名字从oldfname(旧文件名)改为newfname(新文件名)。oldfname和newfname中的目录可以不同,因此可用rename把文件从一个目录移到另一个目录,该函数的原型在“stdio.h”中。函数调用成功时返回0,出错是返回非零值。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include<stdio.h>

(3)调用rename函数给文件的重命名,主要程序代码如下:

        main()
        {
            FILE*fp;                                           /*定义一个指向FILE类型结构体的指针变量*/
            char filename1[20],filename2[20];                  /*定义数组为字符型*/
            printf("please input the file name which do you want to change:\n");
            scanf("%s",filename1);                           /*输入要重命名的文件所在的路径及名称*/
            if((fp=fopen(filename1,"r"))!=NULL)         /*以只读方式打开指定文件*/
            {
                printf("%s open successfully", filename1);
                printf("\nplease input new name!")??scanf("%s",filename2);    /*输入新的文件路径及名称*/
                rename(filename1,filename2);                 /*调用rename函数进行重命名*/
                fclose(fp);                                  /*关闭文件*/
            }
            else
            {
                printf("cannot find!!");
                exit(0);
            }
        }

举一反三

根据本实例,读者可以:

将当前目录中一个任意的文本文档文件的文件名改成“bbb.txt”。

将当F根目录中一个任意的二进制文件的文件名改成“bbb”。

实例181 删除文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\181

实例说明

编程实现文件的删除,具体要求如下:从键盘中输入要删除的文件的路径及名称,无论删除是否成功都在屏幕中给出提示信息。运行结果如图6.15所示。

图6.15 删除文件

技术要点

本实例使用了remove函数,具体使用说明如下。

● remove函数

        int remove(char *filename)

该函数的作用是删除filename所指定的文件。删除成功返回0,出现错误返回-1,remove函数的原型在“stdio.h”中。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include<stdio.h>

(3)调用remove函数删除指定文件,主要程序代码如下:

        main()
        {
            FILE*fp;                                     /*定义一个指向FILE类型结构体的指针变量*/
            char filename[50];                           /*定义数组为字符型*/
            printf("please input the name of the file which do you want to delete:\n");
            scanf("%s",filename);                      /*输入要删除的文件的路径及名称*/
            if((fp=fopen(filename,"r"))!=NULL)    /*以只读方式打开指定文件*/
            {
              printf("%s open successfully!",filename);/*文件打开成功输出提示信息*/
              fclose(fp);                              /*关闭文件*/
            }
            else
            {
              printf("%s cannot open!",filename);      /*文件打开失败输出提示信息*/
              exit(0);
            }
            remove(filename);                          /*调用函数删除文件*/
            if((fp = fopen(filename, "r"))= = NULL)
              printf("\n%s has removed!",filename);    /*若要打开的文件不存在,则删除成功,输出提示信息*/
            else
              printf("error");                         /*若要打开的文件存在,则删除不成功,输出提示信息*/
        }

举一反三

根据本实例,读者可以:

在当前目录中新建一个文本文件并写入内容,将该内容显示在屏幕上后将该文件删除。

任意删除一个指定目录中的文件。

实例182 删除文件中的记录

本实例可以方便操作、提高效率

实例位置:光盘\mingrisoft\06\182

实例说明

编程实现对记录中职工工资信息的删除,具体要求如下:输入路径及文件名打开一文件,录入员工姓名及工资,录入完毕显示文件中的内容,输入要删除的员工姓名,进行删除操作,最后将删除后的内容显示在屏幕上。运行结果如图6.16所示。

技术要点

实现实例之前要把思路理清,思路理清了用前面讲过的函数很容易,就是能实现程序中要求的功能。那么下面就来分析下本题的思路。

首先是打开一个二进制文件,此时打开应以追加的方式打开,要是以只写的方式打开会使文件中原有内容丢失,向该文件中输入员工工资信息,输入完毕将文件中内容全部输出,然后输入要删除的员工的姓名,使用strcmp函数查找相匹配的姓名来确定要删除记录的位置,将该位置后的记录分别前移一位,也就是将要删除的记录用后面的记录覆盖了。最后将删除后剩余的记录使用fwrite再次输出到磁盘文件中,使用fread函数读取文件内容到emp数组中并显示在屏幕上。

图6.16 删除文件中的记录

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>
        #include <string.h>

(3)定义结构体emploee,用来存储员工工资信息,代码如下:

        struct emploee                                           /*定义结构体,存放员工工资信息*/
        {
            char name[10];
            int salary;
        } emp[20];

(4)main()函数作为程序的入口函数,代码如下:

        main()
        {
            FILE*fp1,  *fp2;
            int i, j, n, flag, salary;
            char name[10],filename[50];                                  /*定义数组为字符类型*/
            printf("please input filename:\n");
            scanf("%s",filename);                                      /*输入文件所在路径及名称*/
            printf("please input the number of emploees:\n");
            scanf("%d",&n);                                            /*输入要录入的人数*/
            printf("input name and salary:\n");
            for(i = 0; i < n; i++)
            {
                printf("NO%d:\n", i + 1);
                scanf("%s%d",emp[i].name,&emp[i].salary);              /*输入员工姓名及工资*/
            }
            if((fp1=fopen(filename,"ab"))==NULL)                  /*以追加的方式打开指定的二进制文件*/
            {
                printf("Can not open the file.");
                exit(0);
            }
            for(i = 0; i < n; i++)
                if(fwrite(&emp[i],sizeof(struct emploee),1,fp1)!=1)/*将输入的员工信息输出到磁盘文件上*/
                    printf("error\n");
            fclose(fp1);
            if((fp2 = fopen(filename, "rb"))= = NULL)
            {
                printf("Can not open file.");
                exit(0);
            } printf("\n original data:");
            for(i=0;fread(&emp[i],sizeof(struct emploee),1,fp2)!=0;i++)/*读取磁盘文件上的信息到emp数组中*/
                printf("\n %8s%7d", emp[i].name, emp[i].salary);
            n = i;
            fclose(fp2);
            printf("\n Input name which do you want to delete:");
            scanf("%s",name);                                          /*输入要删除的员工姓名*/
            for(flag = 1, i = 0; flag && i < n; i++)
            {
              if(strcmp(name,emp[i].name)==0)                       /*查找与输入姓名相匹配的位置*/
              {
                    for(j = i; j < n -1; j++)
                    {
                      strcpy(emp[j].name,emp[j+1].name);               /*查找到要删除信息的位置后将后面信息前移*/
                      emp[j].salary = emp[j + 1].salary;
                    }flag=0;                                             /*标志位置0*/
              }
            }
            if(!flag)
              n=n-1;                                                     /*记录个数减1*/
            else
              printf("\nNot found");
            printf("\nNow,the content of file:\n");
            fp2=fopen(filename,"wb");                                  /*以只写方式打开指定文件*/
            for(i = 0; i < n; i++)
              fwrite(&emp[i],sizeof(struct emploee),1,fp2);          /*将数组中的员工工资信息输出到磁盘文件上*/
            fclose(fp2);
            fp2=fopen(filename,"rb");                                  /*以只读方式打开指定二进制文件*/
            for(i=0;fread(&emp[i],sizeof(struct emploee),1,fp2)!=0;i++)/*以只读方式打开指定二进制文件*/
              printf("\n%8s%7d",emp[i].name,emp[i].salary);            /*输出员工工资信息*/
            fclose(fp2);
        }

举一反三

根据本实例,读者可以:

编程实现对记录中学生信息的删除,输入要删除的学生姓名,进行删除操作,最后将删除后的内容显示在屏幕上。

编程实现添加新的学生记录到已有的记录中,要求将修改后的内容显示在屏幕上。

6.4 文件相关操作

在实际应用中经常会有一些文件是不希望被别人看到的,这时最通常的办法是用文件加密器将文件加密,实际上通过C语言编程也可实现该功能,同样通过编程也可对文件进行其他操作,例如文件分割、显示目录内同类型文件等,本节就介绍了几个有关文件操作的相关实例。

实例183 关闭打开的所有文件

本实例可以方便操作、提高效率

实例位置:光盘\mingrisoft\06\183

实例说明

在程序中打开3 个磁盘上已有的文件,读取文件中的内容并显示在屏幕上,要求调用closefileall()函数一次关闭打开的3个文件。运行结果如图6.17所示。

图6.17 关闭打开的所有文件

技术要点

程序中用到fcloseall()函数,具体使用说明如下:

        int fcloseall(void)

该函数的作用是一次关闭所有被打开的文件。如果函数执行成功,它将返回成功关闭文件的数目,如果出错,则返回EOF常量。该函数原型在stdio.h中。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>

(3)使用while循环来读取每个文件中的内容,调用fclosefile()函数关闭打开的所有文件,并将关闭的文件数输出。

(4)主函数程序代码如下:

        main()
        {
            FILE*fp1,  *fp2,  *fp3;                                    /*定义文件类型指针fp1、fp2、fp3*/
            char file1[20], file2[20], file3[20], ch;
            int file_number;                                           /*关闭的文件数目*/
            printf("please input file1:");
            scanf("%s",file1);                                       /*输入文件1的路径及名称*/
            printf("file1:\n");
            if((fp1 = fopen(file1, "rb"))!= NULL)
            {
                ch=fgetc(fp1);                                       /*读取文件1中内容*/
                while(ch != EOF)
                {
                    putchar(ch);
                    ch = fgetc(fp1);
                }
            }
            else
            {
                printf("can not open!");                             /*若文件未打开输出提示信息*/
                exit(1);
            }
            printf("\nplease input file2:");
            scanf("%s",file2);                                       /*输入文件2的路径及名称*/
            printf("file2:\n");
            if((fp2 = fopen(file2, "rb"))!= NULL)
            {
                ch=fgetc(fp2);                                       /*读取文件2中内容*/
                while(ch != EOF)
                {
                    putchar(ch);
                    ch = fgetc(fp2);
                }
            }
            else
            {
                printf("can not open!");
                exit(1);
            }
            printf("\nplease input file3:");
            scanf("%s",file3);                                       /*输入文件3的路径及名称*/
            printf("file3:\n");
            if((fp3 = fopen(file3, "rb"))!= NULL)
            {
                ch=fgetc(fp3);                                       /*读取文件3中内容*/
                while(ch != EOF)
                {
                    putchar(ch);
                    ch = fgetc(fp3);
                }
            }
            else
            {
                printf("can not open!");
            exit(1);
            }
            file_number=fcloseall();                                 /*调用fcloseall()函数关闭打开的文件,将返回值赋给file_number*/
            printf("\n%d files colsed", file_number);
        }

举一反三

根据本实例,读者可以:

编程实现重新打开文件流。

编程实现控制文件打开操作的读写模式。

实例184 同时显示两个文件的内容

本实例可以方便操作、提高效率

实例位置:光盘\mingrisoft\06\184

实例说明

编程实现将两个不同文件中的内容在屏幕中的指定位置显示出来。运行结果如图6.18所示。

图6.18 同时显示两个文件内容

技术要点

本实例中没有太多难点,和前面程序中讲过的输出磁盘文件中内容的方法基本一致,惟一一点值得注意的是程序中使用了gotoxy()函数来指定文件要输出的位置,具体使用说明如下:

        void gotoxy(int x,int y)

该函数的作用是将字符屏幕上的光标移动到由x,y所指定的位置上,如果其中有一个坐标是无效的,则光标不移动。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>
        #include<conio.h>

(3)程序中使用gotoxy()函数指定文件1开始输出的位置是第五行第三列,文件2开始输出的位置是第十三行三列。

(4)main()函数作为程序的入口函数,代码如下:

        main()
        {
            FILE*fp1,  *fp2;                       /*定义两个指向FILE类型结构体的指针变量*/
            char filename1[50],filename2[50],a;    /*定义数组和变量为字符型*/
            printf("please input filename1:\n");
            scanf("%s",filename1);               /*输入第一个文件所在路径及名称*/
            printf("please input filename2\n");
            scanf("%s",filename2);               /*输入第二个文件所在路径及名称*/
            fp1=fopen(filename1,"r");            /*以只读方式打开输入的第一个文件*/
            fp2=fopen(filename2,"r");            /*以只读方式打开输入的第二个文件*/
            gotoxy(3,5);                         /*将光标定位*/
            printf("file1:\n");
            a = fgetc(fp1);
            while(!feof(fp1))
            {
                printf("%c",a);                  /*输出第一个文件中的内容*/
                a = fgetc(fp1);
            }
            gotoxy(3,13);                        /*将光标定位*/
            printf("file2:\n");
            a = fgetc(fp2);
            while(!feof(fp2))
            {
                printf("%c",a);                  /*输出第二个文件中的内容*/
                a = fgetc(fp2);
            }
            fclose(fp1);                         /*关闭第一个文件*/
            fclose(fp2);                         /*关闭第二个文件*/
        }

举一反三

根据本实例,读者可以:

同时显示当前目录中一个文本文档的内容和一个二进制文件的内容。

同时显示当前目录中两个文件的内容,要求背景颜色为蓝色,字体颜色为黄色。

实例185 显示目录内同类型文件

本实例是一个提高基础技能的程序

实例位置:光盘\mingrisoft\06\185

实例说明

编程实现对指定文件中的内容进行统计。具体要求如下:输入要进行统计的文件的路径及名称,统计出该文件中字符、空格、数字及其他字符的个数,并将统计结果存到指定的磁盘文件中。运行结果如图6.19所示。

图6.19 显示目录内同类型文件

技术要点

本实例中用到3个目录函数,分别是chdir()、findfirst()及findnext(),具体使用说明如下。

● chdir()函数

        int chdir(char *path)

该函数的作用是把路径名由path所指的目录变成当前工作目录。这里有一点值得注意就是这个目录必须是已存在的。如果成功,返回0,否则返回-1。该函数的原型包含在“dir.h”头文件中。

● findfirst()与findnext()函数

        int findfirst(char *filename,struct ffblk *ptr,int attrib)
        int findnext(struct ffblk *ptr)

该函数的作用是寻找与filename所指向的文件名相匹配的第一个文件名。如果找到了相匹配的文件,则将有关文件的信息填入由ptr所指向的结构体中。ffblk结构定义如下:

        struct ffblk
        {
        char ff_reserved[2];
        char ff_attrib;
        int ff_ftime;
        int ff_fdate;
        long ff_fsize;
        char ff_name[13];
        };

参数attrib决定了由findfirst()函数要找的文件的类型。属性attrib可以是下面各个宏之一,如表6.4所示。

表6.4 参数attrib取值

函数findnext()将继续由findfirst()开始的搜索。函数findfirst()和findnext()若成功返回0,失败则返回-1。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件:

        #include <stdio.h>
        #include <dir.h>
        #include <dos.h>

(3)程序中先使用findfirst()查找与输入文件类型相匹配的第一个文件名,用i来表示findfirst()的返回值,当i=0时,说明查找到第一个文件,否则说明该目录下没有与输入的文件类型相匹配的文件,输出提示信息后便退出程序。若存在第一个文件再使用findnext()函数继续进行搜索,程序中用j来表示findnext()的返回值,当j恒等于0时则继续进行下次查找,当j不等于0时,说明查找结束。

(4)main()函数作为程序的入口函数,代码如下:

        main()
        {
            char str1[50],str2[50],filename[50];     /*定义数组为字符型*/
            int i,j=0,k;                             /*定义变量为基本整型*/
            FILE*fp;                                 /*定义一个指向FILE类型结构体的指针变量*/
            struct ffblk fileinf;
            printf("please input filename which do you want to save:");
            gets(filename);
                                                     /*输入磁盘文件路径及名称,该文件用来保存统计出的结果*/
            fp = fopen(filename, "w+");
            printf("Please input directory:\n");   /*提示输入目录*/
            gets(str1);                            /*输入要进行统计的文件所在目录*/
            k=chdir(str1);                         /*切换当前工作目录,正确返回0*/
            if(k!=0)                              /*如果不等于0,提示信息后退出*/
            {
                printf("Change Path failure!\n");
                getch();
                exit(-1);
            }
            printf("\nPlease input File type:\n");
            gets(str2);                            /*输入要进行统计的文件的类型,如:*.doc*/
            i=findfirst(str2,&fileinf,FA_ARCH);    /*查找匹配条件的第一个文件,正确返回0*/
            if(i!=0)                              /*如果返回值不为0,提示信息后退出*/
            {
                printf("File Not Find!\n");
                getch();
                exit(-1);
            }
            else
            {
                printf("\n");
                printf("%s\n",fileinf.ff_name);    /*在屏幕上打印*/
                fputs(fileinf.ff_name,fp);         /*输出到文件*/
                fputs("\n",fp);                    /*输出换行符到文件*/
                while(j==0)                       /*循环查找,直到findnext不等于0*/
                {
                    j=findnext(&fileinf);          /*查找与findfirst相匹配的文件*/
                    if(j = = 0)
                    /*如果找到*/
                    {
                        printf("%s\n",fileinf.ff_name);/*在屏幕上打印*/
                        fputs(fileinf.ff_name,fp); /*输出到文件*/
                        fputs("\n",fp);            /*输出换行符到文件*/
                    }
                }
            }
            fclose(fp);                            /*关闭文件*/
        }

举一反三

根据本实例,读者可以:

编程实现分解文件路径。

编程实现显示指定文件的属性。

实例186 文件分割

这是一个可以启发思维的实例

实例位置:光盘\mingrisoft\06\186

实例说明

编程实现将一个较大的文件分割成若干个较小的文件,要求分割成的文件不改变原有文件内容。运行结果如图6.20所示。

图6.20 文件分割

技术要点

本实例在编写程序的时候有以下几点需要注意。

(1)文件的扩展名问题:要生成新的文件就要给新的文件命名,命名的过程中就要注意一方面不能重复命名,另一方面新文件要与原文件的扩展名一致。程序中使用了数组ext来存储带扩展名的文件名,用来与输入的文件名连接以保证文件名不同但文件类型一致。

(2)ftell函数的使用,该函数的作用是得到流式文件中的当前位置,用相对于文件开头的位移量来表示。

(3)ftell与fseek函数结合使用,用来统计要进行分割的文件共有多少字节。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件并定义全局变量:

        #include <stdio.h>
        #include <string.h>
        #include <stdlib.h>
        FILE*in,  *out;                                         /*定义两个指向FILE类型结构体的指针变量*/
        char filename[50], ch, cfilename[50];

(3)自定义space()函数,用来实现文件的分割,代码如下:

        void space()                                               /* 分隔文件函数 */
        {
            char ext[6][6] =
            {
              "a.txt", "b.txt", "c.txt", "d.txt", "e.txt", "f.txt"
            };                                                        /* 分割出来的文件扩展名 */
            unsigned long int n=1,k,byte=0;                           /* 定义变量类型为无符号的长整形变量 */
            unsigned int j = 0, i = 0;
            printf("Please input filename:\n");
            scanf("%s",filename);                                   /*输入文件所在路径及名称*/
            strcpy(cfilename,filename);                             /*输入文件所在路径及名称复制到cfilename中*/
            if((in=fopen(filename,"r"))==NULL)                 /* 以只读方式打开输入文件 */
            {
              printf("Cannot open file\n");
              exit(0);
            }
            printf("Please input file size after space(kb):\n");
            scanf("%d",&n);                                         /* 输入分割后单个文件的大小 */
            n = n * 1024;
            while(filename[j] != '.')
              j++;
            filename[j]='\0';                                         /*遇'.'时,在该处加字符串结束符*/
            if((out=fopen(strcat(filename,ext[i]),"w"))==NULL)/*生成分割后文件所在路径及名称*/
            {
              printf("Cannot open file\n");
              exit(0);
            }
            fseek(in,0,2);                                          /*将位置指针移到文件末尾*/
            k=ftell(in);                                            /*k存放当前位置,也就是整个文件的大小 */
            fseek(in, 0, 0);
            while(k > 0)
            {
              ch = fgetc(in);
              fputc(ch, out);
              byte++;                                                 /*字节数增加*/
              k--;                                                    /*大小减1*/
              if(byte==n)                                          /*当为要求的大小时执行括号内语句*/
              {
                    fclose(out);                                    /*完成一个分割出的文件*/
                    byte=0;                                           /*byte重新置0*/
                    strcpy(filename,cfilename);                     /*filename恢复初始状态*/
                    while(filename[j] != '.')
                      j++;
                    filename[j]='\0';                                 /*遇'.'时,在该处加字符串结束符*/
                    i++;
                    if((out = fopen(strcat(filename, ext[i]), "w"))= = NULL)
                                                                      /*生成分割后文件所在路径及名称*/
                    {
                        printf("Cannot open file\n");
                        exit(0);
                    }
                }
            }
            fclose(in);                                             /* 关闭文件 */
            printf("File succeed space!\n\n\n");
        }

(4)main()函数作为程序的入口函数,代码如下:

        main()                                                /* 程序主函数 */
        {
            printf(" now file space!\n");
            space();
        }

举一反三

根据本实例,读者可以:

编程实现将分割后的文件重新合并。

编程实现将分割后的文件放到不同文件夹中。

实例187 文件加密

这是一个可以启发思维的实例

实例位置:光盘\mingrisoft\06\187

实例说明

编程实现文件加密,具体要求如下:先从键盘中输入要加密操作的文件所在的路径及名称,再输入密码,最后输入加密后的文件要存储路径及名称。运行结果如图6.21所示。

图6.21 统计文件内容

技术要点

加密的算法思想如下:对文本文档中的内容进行加密,实质上就是读取该文档中的内容,对读出的每个字符与输入的密码进行异或,再将异或后的内容重新写入指定的磁盘文件中即可。

实现过程

(1)在TC中创建一个C文件。

(2)引用头文件并进行函数声明:

        #include<stdio.h>                                     /*标准输入输出头文件*/
        #include <stdlib.h>
        #include <string.h>
        void encrypt(char*soucefile,char*pwd,char*codefile);/*对文件进行加密的具体函数*/

(3)自定义encrypt()函数,作用是实现对指定文件进行加密,代码如下:

        void encrypt(char*s_file,char*pwd,char*c_file)   /*自定义函数encrypt用于加密*/
        {
            int i = 0;
            FILE*fp1,  *fp2;                                /*定义fp1和fp2是指向结构体变量的指针*/
            register char ch;
            fp1 = fopen(s_file, "rb");
            if(fp1 = = NULL)
            {
              printf("cannot open s_file.\n");
              exit(1);                                    /*如果不能打开要加密的文件,便退出程序*/
            }
            fp2 = fopen(c_file, "wb");
            if(fp2 = = NULL)
            {
              printf("cannot open or create c_file.\n");
              exit(1);                                    /*如果不能建立加密后的文件,便退出*/
            }
            ch = fgetc(fp1);
            while(!feof(fp1))                          /*测试文件是否结束*/
            {
              ch=ch^*(pwd+i);                             /*采用异或方法进行加密*/
              i++;
              fputc(ch,fp2);                              /*异或后写入fp2文件*/
              ch = fgetc(fp1);
              if(i > 9)
                    i = 0;
            }
            fclose(fp1);                                  /*关闭源文件*/
            fclose(fp2);                                  /*关闭目标文件*/
        }

(4)main()函数作为程序的入口函数,代码如下:

        main(int argc,char*argv[])                        /*定义main()函数的命令行参数*/
        {
            char sourcefile[50];                             /*用户输入的要加密的文件名*/
            char codefile[50];
            char pwd[10];                                    /*用来保存密码*/
            if(argc!=4)                                   /*容错处理*/
            {
              printf("please input encode file name:\n");
              gets(sourcefile);                            /*得到要加密的文件名*/
              printf("please input Password:\n");
              gets(pwd);                                   /*得到密码*/
              printf("please input saved file name:\n");
              gets(codefile);                              /*得到加密后你要的文件名*/
              encrypt(sourcefile, pwd, codefile);
            }
            else
            {
              strcpy(sourcefile, argv[1]);
              strcpy(pwd, argv[2]);
              strcpy(codefile, argv[3]);
              encrypt(sourcefile, pwd, codefile);
            }
        }

举一反三

根据本实例,读者可以:

编程实现改变一个指定文件的长度。

编写文件解密程序。