C语言合并文件(附带源码)

文本文件 f01.txt 和 f02.txt 中都保存着已经排好序(从小到大)的若干整数数据。请编写程序将文件 f01.txt 和 f02.txt 中的所有数据合并在一起,保存为文件 f.txt,并且使得合并后的数据也按从小到大的顺序排列。

问题分析

这个问题与复制文件问题的不同之处在于读取文件中的数据时以整数读取,因而可以使用文件的格式化读取函数 fscanf( ) 来读取数据,而且每读取一个整数后,文件的位置指针则指向下一个读取对象(整数或文件末尾标识符 EOF)。同样地,向文件中写入数据则使用格式化写入函数 fprintf( )。

算法描述

1) 定义文件指针分别指向两个输入文件和一个输出文件;
2) 定义两个整型变量 x 和 y 分别存放从两个输入文件中读取到的数据;
3) 当两个输入文件均未读完时(位置指针还未指向文件末尾),重复执行:
       (a)如果是首次读取,则分别从两个输入文件中读入一个数据,赋值给 x 和 y;
           否则,比较 x 和 y,从读取到较小数据的文件中再次读入一个数据;
       (b)比较 x 和 y,将较小的数据写入输出文件;
4) 当读取得 x 的输入文件还未读完时,重复执行:
       (a)如果 x<y,则再次在该文件中读入一个数据赋值给变量 x;
                 再次比较 x 和 y,如果 x<y,将 x 的值写入输出文件;
                                            否则,将 y 的值写入输出文件;
       (b)否则,将 x 的值写入输出文件,再次从该文件读入一个数据赋值给 x;
5) 当读取得 y 的输入文件还未读完时,重复执行:
       (a)如果 x>y,则再次在该文件中读入一个数据赋值给变量 y;
                 再次比较 x 和 y,如果 x>y,将 y 的值写入输出文件;
                                            否则,将 x 的值写入输出文件;
       (b)否则,将 y 的值写入输出文件,再次从该文件中读入一个数据赋值给 y;
6) 输出最后一个 x 或 y,并关闭所有文件;
7) 结束。


代码清单 1:文件合并
#include <stdio.h>
#include <stdlib.h>
int main( )
{
    FILE *fp1, *fp2, *fp;
  int m, x, y;
  fp1 = fopen("f01.txt","r");
  fp = fopen("f.txt","w");
  fp2 = fopen("f02.txt","r");
   m = 0;   //A:读取文件前
  char line[60];
  while(!feof(fp1) && !feof(fp2)) {    //C:循环执行
      if (m == 0) {            //C0:首次读取
        fscanf(fp1,"%d",&x);
      fscanf(fp2,"%d",&y);
      m = 1;
    }
    else {
        if (x < y)
          fscanf(fp1,"%d",&x);    //C1:读取下一个 x
      else
        fscanf(fp2,"%d",&y);    //C2:读取下一个 y
     }
     if (x < y)
        fprintf(fp,"%d ",x);      //C3:输出较小的 x
    else
      fprintf(fp,"%d ",y);      //C4:输出较小的 y
    }
  while(!feof(fp1)) {  //D:文件 f01.txt 未读完时循环执行
      if (x < y) {   //D1:文件 f02.txt 的最后值大于 x 时
        fscanf(fp1,"%d",&x);       //D0:读取下一个 x
      if (x < y)
          fprintf(fp,"%d ",x);     //D3:输出较小的 x
      else
        fprintf(fp,"%d ",y);     //D4:输出较小的 y
    }
    else {      //D2:文件 f02.txt 的最后值小于 x 时
        fprintf(fp,"%d ",x);       //D5:输出 x
      fscanf(fp1,"%d ",&x);      //D6:再次从 f01.txt 读取数据
    }
    }
    while(!feof(fp2)) {   //E:文件 f02.txt 未读完时循环执行
      if (x > y) {     //E1:文件 f01.txt 的最后值大于 y 时
        fscanf(fp2,"%d",&y);          //E0:读取下一个 y
      if (x > y)
          fprintf(fp,"%d ",y);        //E3:输出较小的 y
      else
        fprintf(fp,"%d ",x);        //E4:输出较小的 x
     }
    else {       //E2:文件 f01.txt 的最后值小于 y 时
        fprintf(fp,"%d ",y);          //E5:输出 y
      fscanf(fp2,"%d",&y);           //E6:从 f02.txt 读取数据
    }
    }
  if (x < y)
      fprintf(fp,"%d ",y);       //F1:输出最后 y
  else
    fprintf(fp,"%d ",x);       //F2:输出最后 x
  fclose(fp1);
  fclose(fp2);
  fclose(fp);
  fp1 = fopen("f01.txt","r");
  fgets(line, 60, fp1);
  printf("f01.txt的内容为:%s\n", line);
  fp2 = fopen("f02.txt","r");
  fgets(line, 60, fp2);
  printf("f02.txt的内容为:%s\n", line);
  fp = fopen("f.txt","r");
   fgets(line, 60, fp);
  printf("合并后f.txt的内容为:%s", line);
  fclose(fp1);
  fclose(fp2);
  fclose(fp);
  return 0;
}

运行结果为:

f01.txt的内容为:1 2 5 9
f02.txt的内容为:3 4 6 7 10 15 20
合并后f.txt的内容为:1 2 3 4 5 6 7 9 10 15 20


假如文件 f01.txt 和 f02.txt 的内容如下所示:

f01.txt:1 2 5 9
f02.txt:3 4 6 7 10 15 20


在程序运行过程中,各变量变化情况、两个输入文件的当前读写位置指针指向情况和输出文件 f.txt 的内容变化如表 1 所示。

表 1:代码清单 1 的程序运行过程中各变量的值及文件读写位置指针的变化情况
执行点 变量 m    fp1    变量 x    fp2    变量 y 输出文件:f.txt
A 0 →1      →3          
C0 1 →2 1 →4 3  
C3 1 →2 1 →4 3 1
C1 1 →5 2 →4 3 1
C3 1 →5 2 →4 3 1 2
C1 1 →9 5 →4 3 1 2
C4 1 →9 5 →4 3 1 2 3
C2 1 →9 5 →6 4 1 2 3
C4 1 →9 5 →6 4 1 2 3 4
C2 1 →9 5 →7 6 1 2 3 4
C3 1 →9 5 →7 6 1 2 3 4 5
C1 1 EOF 9 →7 6 1 2 3 4 5
C4 1 EOF 9 →7 6 1 2 3 4 5 6
E0 1 EOF 9 →10 7 1 2 3 4 5 6
E3 1 EOF 9 →10 7 1 2 3 4 5 6 7
E0 1 EOF 9 →15 10 1 2 3 4 5 6 7
E4 1 EOF 9 →15 10 1 2 3 4 5 6 7 9
E5 1 EOF 9 →15 10 1 2 3 4 5 6 7 9 10
E6 1 EOF 9 →20 15 1 2 3 4 5 6 7 9 10
E5 1 EOF 9 →20 15 1 2 3 4 5 6 7 9 10 15
E6 1 EOF 9 EOF 20 1 2 3 4 5 6 7 9 10 15
F1 1 EOF 9 EOF 20 1 2 3 4 5 6 7 9 10 15 20

在程序运行中,确保读取出所有的整数,同时也确保将所有读取出的整数输出到输出文件。