【问题标题】:How to merge the contents of two files into a new file, appearing side by side by line?如何将两个文件的内容合并成一个新文件,并排显示?
【发布时间】:2020-07-31 15:25:26
【问题描述】:

我一直在尝试将两个.txt 文件的内容合并到第三个.txt 文件中,该文件结合了输出。然而,我所知道的(以及我所能找到的所有答案)是通过将第一个文件的内容放在第一位,然后将第二个文件的内容放在第二位来合并它们。但是,我希望输出列出第一个文件的第一行,然后是第二个文件的第一行——然后在新行上依次是第一个文件的第二行和第二个文件的第二行。

为了使这一点在视觉上更清晰,代码当前显示为:

file1-line1
file1-line2
file1-line3
file2-line1
file2-line2
file2-line3

...当我希望它显示为:

file1-line1 file2-line1
file1-line2 file2-line2
file1-line3 file2-line3

我的代码非常基础,可以很好地执行第一个示例:

int main() 
{ 
   FILE *pointer1 = fopen("file1.txt", "r"); 
   FILE *pointer2 = fopen("file2.txt", "r"); 
   FILE *pointer3 = fopen("combined.txt", "w"); 
   int ch; 
  
   if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL) 
   { 
         puts("Could not open files"); 
         exit(0); 
   } 
  
   while ((ch = fgetc(pointer1)) != EOF) 
      fputc(ch, pointer3); 
  
   while ((ch = fgetc(pointer2)) != EOF) 
      fputc(ch, pointer3); 
  
   printf("Merged file1.txt and file2.txt into combined.txt"); 
  
   fclose(pointer1); 
   fclose(pointer2); 
   fclose(pointer3); 
   return 0; 
}

有没有办法输出所描述的情况?我知道E0F 指的是文件的结尾,并且可能会导致问题。行尾是否有类似的情况(如 E0L)?


编辑:将char ch 更改为int ch

【问题讨论】:

  • 如果您使用行,使用fgets 更容易,或者使用fgetc 阅读直到行尾。使用运行的 while 循环,同时您可以从两个文件中获取一行。一旦任何文件用完,只需写入另一个文件的剩余部分。
  • 一般情况下,打开文件出错会被视为失败。因此,您应该编写错误消息并以非零值退出,而不是写入输出并以 0 退出。例如perror("file1.txt"); exit(1);
  • 我投票结束,因为该问题缺乏对特定编程问题的关注。我的意思是 OP 所取得的成就与他们的目标相去甚远,无法通过一个 Q/A 来处理。我的建议是分成更小的步骤,并将这个问题改为只关注第一步 - 或其问题。我建议作为第一步从交错的两个文件中获取输入,即:file1-line1、file2-line1、file1-line2、file2-line2、file1-line3、file2-line3。下一步是询问如何在一行中分别放置两行。
  • 小而重要的一点:char ch; 应该是 int ch;(看看库函数原型)虽然你可能在文本文件处理中“侥幸逃脱”,但你不会你处理一个二进制文件。
  • 尝试一次读取一个字符。当您看到换行符时,请更改您正在读取的文件,并根据需要写入换行符或分隔符。

标签: c pointers file-io


【解决方案1】:

首先,如果你有一个类 Unix 系统,paste 命令已经做到了。接下来,当您要处理行时,您应该使用fgets。在这里,您必须一次循环遍历输入文件一行,将这些行复制到不带换行符的输出文件中,并在复制所有内容后添加新行。

由于两个输入文件的处理是相同的,而且我很懒,所以我写了一个只写一次的函数。最后的代码可能是:

FILE *copyline(FILE *in, FILE *out) {
    char line[256];
    if (in != NULL) {
        for (;;) {       // loop if the line is larger that sizeof(line)
            if (NULL == fgets(line, sizeof(line), in)) { // EOF on file1
                fclose(in);
                in = NULL;
                break;
            }
            size_t end = strcspn(line, "\n");
            if (end != 0) fwrite(line, 1, end, out);   // smth to write
            if (end != strlen(line)) break;       // \n found: exit loop
        }
    }
    return in;
}
int main()
{
    FILE *pointer1 = fopen("file1.txt", "r");
    FILE *pointer2 = fopen("file2.txt", "r");
    FILE *pointer3 = fopen("combined.txt", "w");
    const char sep[] = " ";          // a separator between lines of both file

    if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL)
    {
        puts("Could not open files");
        exit(0);
    }

    for (;;) {
        pointer1 = copyline(pointer1, pointer3);
        fwrite(sep, strlen(sep), 1, pointer3);
        pointer2 = copyline(pointer2, pointer3);
        if (pointer1 == NULL && pointer2 == NULL) break;
        fputc('\n', pointer3);  // if smth was written, add a newline
        printf(".");
    }

    printf("Merged file1.txt and file2.txt into combined.txt");

    fclose(pointer3);
    return 0;
}

【讨论】:

  • 您可以将if (end != strlen(line)) break; 替换为if (line[end] == '\n') break; 或简单的if (line[end]) break;。不需要strlen 呼叫。 line[end] 的值将是 \n\0
【解决方案2】:

这是处理它的一种方法:

#include <err.h>                                                                   
#include <libgen.h>                                                                
#include <stdio.h>                                                                 
#include <stdlib.h>                                                                
                                                                                   
FILE *                                                                             
xfopen(const char *path, const char *mode)                                         
{                                                                                  
        FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :         
                *mode == 'r' ? stdin : stdout;                                     
        if( fp == NULL ) {                                                         
                perror(path);                                                      
                exit(EXIT_FAILURE);                                                
        }                                                                          
        return fp;                                                                 
}                                                                                  
   

int                                                                                
main(int argc, char **argv)                                                        
{                                                                                  
        if( argc < 3 ) {                                                           
                printf("usage: %s file1 file2\n", basename(argv[0]));              
        }                                                                          
        FILE *pointer1 = xfopen(argv[1], "r");                                     
        FILE *pointer2 = xfopen(argv[2], "r");                                     
        FILE *current = pointer1;                                                  
        int ch;                                                                    
                                                                                   
        while( ( ch = fgetc(current)) != EOF ) {                                   
                if( ch == '\n' ) {                                                 
                        if( current == pointer1 ) {                                
                                int k;                                             
                                current = pointer2;                                
                                if( (k = fgetc(current)) != EOF ) {                
                                        ungetc(k, current);                        
                                        ch = ' ';                                  
                                }                                                  
                        } else {                                                   
                                current = pointer1;                                
                        }                                                          
                }                                                                  
                putchar(ch);                                                       
        }                                                                          
        if( ferror(current) ) {                                                    
                err(EXIT_FAILURE, "Error reading %s",                              
                        current == pointer1 ? argv[1] : argv[2]);                  
                                                                                   
        }                                                                          
        current = current == pointer1 ? pointer2 : pointer1;                       
        while( (ch = fgetc(current)) != EOF) {                                     
                putchar(ch);                                                       
        }                                                                          
                                                                                   
        fclose(pointer1);                                                          
        fclose(pointer2);                                                          
        return 0;                                                                  
}  

【讨论】:

    【解决方案3】:
    #include <stdio.h>
    
    int main()
    {
      FILE *pointer1 = fopen("file1.txt", "r");
      FILE *pointer2 = fopen("file2.txt", "r");
      FILE *pointer3 = fopen("combined.txt", "w");
      char ch1, ch2;
    
      if (pointer1 == NULL || pointer2 == NULL || pointer3 == NULL)
      {
        puts("Could not open files");
        return 0;
      }
    
      do
      {
        char c1 = fgetc(pointer1);
        char c2 = fgetc(pointer2);
        if (feof(pointer1) || feof(pointer2))
          break;
    
        while(c1!='\n')
        {
          fputc(c1,pointer3);
          c1=fgetc(pointer1);
          if(feof(pointer1)) break;
        }
    
        fputc(' ',pointer3);
    
        while(c2!='\n')
        {
          fputc(c2,pointer3);
          c2=fgetc(pointer2);
          if(feof(pointer2)) break;
        }
          
        fputc('\n',pointer3);
      } while (1);
    
      printf("Merged file1.txt and file2.txt into combined.txt");
    
      fclose(pointer1);
      fclose(pointer2);
      fclose(pointer3);
      return 0;
    }
    

    这如你所愿。

    输出:组合文件.txt

    file1-line1 file2-line1
    file1-line2 file2-line2
    file1-line3 file2-line3
    

    【讨论】:

    • 这是 feof 的错误我们。如果您遇到读取错误,您将陷入无限循环,因为feof 将不断返回 false。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    相关资源
    最近更新 更多