【问题标题】:How do I merge two sorted files into one sorted file?如何将两个已排序的文件合并为一个已排序的文件?
【发布时间】:2019-10-06 14:58:19
【问题描述】:

更具体地说,我想将两个排序的整数列表合并到第三个也排序的列表中。我不知道为什么我的代码不起作用!这是一些条目示例和我制作的代码:

文件1:

1
2
3
4
5
6

文件2:

7
8
9
9
9
10

C 代码:

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

void merge(char* arq1, char* arq2){
    FILE* final;
    final = fopen("merge.txt",'w');
    FILE* f1 = fopen(arq1,'rt');
    FILE* f2 = fopen(arq2,'rt');
    if(!f1 || !f2) exit(1);
    // n1 and n2 represents the actual value that's been read. r1 and r2 the status of each file.
    int n1,n2,r1,r2,equal;
    r1 = fscanf(f1,"%d",&n1);
    r2 = fscanf(f2,"%d",&n2);
    while(r1 || r2){
         if((!r1) || (n2 < n1)){
            fprintf(final,"%d ",n2);
            r2 = fscanf(f2,"%d",&n2);
        }else if((!r2) || (n1 < n2)){
            fprintf(final,"%d ",n1);
            r1 = fscanf(f1,"%d",&n1);
        }else{
            equal = n1;
            fprintf(final,"%d ",equal);
            while(n1 == equal) r1 = fscanf(f1,"%d",&n1);
            while(n2 == equal) r2 = fscanf(f2,"%d",&n2);
        }
    }
    fclose(final);
    fclose(f1);
    fclose(f2);
}

int main(int argc, char const *argv[]){
    merge("merge1.txt","merge2.txt"); 

    return 0;
}

算法应该如下工作:

虽然至少其中一个文件仍有内容,但其内容随后将保存在merge.txt 文件中。如果文件 1 和 2 具有相同的内容,我会保存内容并读取这 2 个文件,直到它们找到不同的值,这样合并后的文件就不会有重复的值。

如何将两个排序后的文件合并为一个排序后的文件?

【问题讨论】:

  • 到底是怎么回事?输出是什么?
  • 听你的编译器警告; fopen 的 mode 参数的字符串需要由 " 分隔。
  • 另外:fscanf() 可以返回 EOF。
  • 请注意,如果两个文件中出现相同的数字,您的合并代码只会消除重复项。如果其中一个文件包含另一个文件不包含的重复项,则会保留这些重复项。此外,您的样本数据不是一个好的测试数据集。您需要两个文件中具有重叠范围的样本数据,而不是所有文件 A 都在文件 B 之前。
  • 首先,非常感谢,我完全忘记了双引号和单引号。至于测试,应该是很简单的练习,虽然我真的没想到会出现这种情况。我现在很乐意更正我的代码。

标签: c file merge


【解决方案1】:
  1. fopen() 的模式参数应该是一个字符串。

  2. fscanf() 可以在错误或 EOF 时返回 EOF(-1)

  3. 失败时,fscanf() 的目标变量的值未定义。


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

void merge(char* arq1, char* arq2){
    FILE *final;
    final = fopen("merge.txt", "w"); // <<--(1)
    FILE *f1 = fopen(arq1, "rt"); // <<--(1)
    FILE *f2 = fopen(arq2, "rt"); // <<--(1)
    if(!f1 || !f2 || !final) exit(1); // <<--(1)
    // n1 and n2 represents the actual value that's been read. r1 and r2 the status of each file.
    int n1,n2,r1,r2,equal;

    r1 = fscanf(f1, "%d", &n1);
    r2 = fscanf(f2, "%d", &n2);
    while(r1>0 || r2>0){ // <<--(2)
         if(r1 < 1 || n2 < n1){ // <<--(2)
            fprintf(final, "%d ", n2);
            r2 = fscanf(f2, "%d", &n2);
        }else if(r2 < 1 || n1 < n2){ // <<--(2)
            fprintf(final, "%d ", n1);
            r1 = fscanf(f1, "%d", &n1);
        }else{
            equal = n1;
            fprintf(final, "%d ", equal);
            while(n1 == equal && r1 > 0) r1 = fscanf(f1, "%d", &n1); // <<--(2,3)
            while(n2 == equal && r2 > 0) r2 = fscanf(f2, "%d", &n2); // <<--(2,3)
        }
    }
    fclose(final);
    fclose(f1);
    fclose(f2);
}

int main(int argc, char const *argv[]){
    merge("merge1.txt","merge2.txt"); 

    return 0;
}

【讨论】:

    【解决方案2】:

    OP 发布的代码无法干净编译!

    这是编译器的输出:

    gcc    -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11  -c "untitled.c"  
    
    untitled.c: In function ‘merge’:
    untitled.c:6:31: warning: passing argument 2 of ‘fopen’ makes pointer from integer without a cast [-Wint-conversion]
         final = fopen("merge.txt",'w');
                                   ^~~
    
    In file included from untitled.c:1:0:
    /usr/include/stdio.h:232:14: note: expected ‘const char * restrict’ but argument is of type ‘int’
     extern FILE *fopen (const char *__restrict __filename,
                  ^~~~~
    
    untitled.c:7:27: warning: multi-character character constant [-Wmultichar]
         FILE* f1 = fopen(arq1,'rt');
                               ^~~~
    
    untitled.c:7:27: warning: passing argument 2 of ‘fopen’ makes pointer from integer without a cast [-Wint-conversion]
    
    In file included from untitled.c:1:0:
    /usr/include/stdio.h:232:14: note: expected ‘const char * restrict’ but argument is of type ‘int’
     extern FILE *fopen (const char *__restrict __filename,
                  ^~~~~
    
    untitled.c:8:27: warning: multi-character character constant [-Wmultichar]
         FILE* f2 = fopen(arq2,'rt');
                               ^~~~
    
    untitled.c:8:27: warning: passing argument 2 of ‘fopen’ makes pointer from integer without a cast [-Wint-conversion]
    
    In file included from untitled.c:1:0:
    /usr/include/stdio.h:232:14: note: expected ‘const char * restrict’ but argument is of type ‘int’
     extern FILE *fopen (const char *__restrict __filename,
                  ^~~~~
    
    untitled.c: In function ‘main’:
    untitled.c:33:14: warning: unused parameter ‘argc’ [-Wunused-parameter]
     int main(int argc, char const *argv[]){
                  ^~~~
    
    untitled.c:33:32: warning: unused parameter ‘argv’ [-Wunused-parameter]
     int main(int argc, char const *argv[]){
                                    ^~~~
    

    关于:

    final = fopen("merge.txt",'w');
    

    'mode' 参数必须是字符串。建议在 'mode' 参数周围使用双引号:

    final = fopen("merge.txt","w");
    

    关于:

    FILE* f1 = fopen(arq1,'rt');
    

    和以前一样,'mode' 参数必须是一个字符串。建议:

    FILE* f1 = fopen(arq1,"rt");
    

    main()函数,由于没有用到参数,建议使用签名:

    int main( void )
    

    编译时,始终启用警告,然后修复这些警告

    【讨论】:

    • OPs 代码由于编译问题而无法正常工作,为什么要投反对票?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 2014-09-18
    相关资源
    最近更新 更多