【问题标题】:Comparing two files in c [closed]比较c中的两个文件[关闭]
【发布时间】:2013-03-23 23:56:16
【问题描述】:

正如标题所说,我需要比较 2 个文件。如果出现一行,这两个文件之间不一样,请打印该行(来自两个文件)。代码给出了不发送错误。我似乎无法在我的代码中找到错误。

#include <stdio.h>
#include <string.h>
#define MAX 1000

int main(int argc, char *argv[]) {
    char c1, c2;
    char s1[MAX], s2[MAX];
    char *p1;
    char *p2;
    FILE *fp1;
    FILE *fp2;
    fp1 = fopen(argv[1], "r");
    fp2 = fopen(argv[2], "r");
    p1 = s1;
    p2 = s2;
    if (argc != 3) {
        printf("Wrong use of program \n ");
        return -1;
    }
    if (fp1 == NULL || fp2 == NULL) {
        printf("One or both of the files can't be used \n ");
        return -1;
    }
    while ((c1 = getc(fp1)) != EOF || (c2 = getc(fp2)) != EOF) {
        *p1 = c1;
        *p2 = c2;
        p1++;
        p2++;

        for (c1 = getc(fp1); c1 != '\n'; p1++) {
            *p1 = c1;
        }
        *p1 = '\0';

        for (c2 = getc(fp2); c2 != '\n'; p2++) {
            *p2 = c2;
        }
        *p2 = '\0';
        if (!(strcmp(s1, s2))) {
            printf("%s \n ", s1);
            printf("%s \n ", s2);
            return 0;
        }
    }
    return 0;
}

【问题讨论】:

  • 一个不发送错误
  • 编译所有警告和调试信息(例如 Linux 上的 gcc -Wall -g)并学习如何使用调试器(例如 Linux 上的 gdb)。
  • 首先,我会查看您将字符串分配给s1s2 的位置。
  • while 循环中的 2 个 fgets() 和一个 strcmp() 有什么问题?
  • 还要考虑如果您的文件以单个换行符结尾或未以换行符终止的行...

标签: c file compare argv argc


【解决方案1】:

如果这两个文件是文本文件,那么老实说,我会从头开始使用一个更简单的程序,该程序使用 fgets() 而不是 getc(),并使用 strcmp() 而不是逐个字符地逐行比较。代码中的错误太多了 - 如果您放弃现有的内容并使用更简单的解决方案重新开始,您将更快地完成任务。

顺便说一句,如果两个字符串相同,strcmp 返回零,如果不同,则返回非零。

【讨论】:

    【解决方案2】:

    在两个for 循环中,您在循环的初始化部分有getc,它将在c1c2 中放置一个字符,然后执行循环,直到超出s1s2 通过您的 p1p2 指针。由于永远不会遇到c1 != '\n',除非您在该行中的第一个字符是“\n”,它可能会引发分段错误错误。

    while 上,至少在 gcc 和我的系统上,它会进行惰性评估(编辑:不是惰性而是短路评估,请参阅 cmets),如果另一部分是,则不会执行 c2 = getc(fp2) 部分真的。

    您也不要在每行之后重置 p1p2

    strcmp 如果两个字符串相等,则返回 0,而在 C 中,0 为假,非零为真,因此您将在第一次匹配时退出。

    这是您的代码的一个几乎无法运行的版本,您仍然需要处理它并考虑到一个文件比另一个文件短,文件中的一行大于 1000 个字符(就像现在一样)它会溢出s1s2),等等。

    #include <stdio.h>
    #include <string.h>
    #define MAX 1000
    
    int main(int argc, char *argv[]) {
      char c1, c2;
      char s1[MAX], s2[MAX];
      char *p1;
      char *p2;
      FILE *fp1;
      FILE *fp2;
      p1 = s1;
      p2 = s2;
      if (argc != 3) {
        printf("Wrong use of program \n ");
        return -1;
      }
      fp1 = fopen(argv[1], "r");
      fp2 = fopen(argv[2], "r");
      if (fp1 == NULL || fp2 == NULL) {
        printf("One or both of the files can't be used \n ");
        return -1;
      }
      c1 = getc(fp1);
      c2 = getc(fp2);
      while ((c1 != EOF) && (c2 != EOF)) {
        for (; c1 != '\n'; p1++) {
            *p1 = c1;
            c1 = getc(fp1);
        }
        *p1 = '\0';
    
        for (; c2 != '\n'; p2++) {
            *p2 = c2;
            c2 = getc(fp2);
        }
        *p2 = '\0';
        if ((strcmp(s1, s2)) != 0) {
            printf("%s\n", s1);
            printf("%s\n", s2);
            return 0;
        }
        c1 = getc(fp1);
        c2 = getc(fp2);
        p1 = s1;
        p2 = s2;
      }
      if (c1 != EOF || c2 != EOF)
        printf("One of the files ended prematurely\n");
      return 0;
    }
    

    【讨论】:

    • 谢谢,这正是我所需要的。我知道如果一行大于 1000 会导致错误,我现在只想用更少的行测试代码。
    • 澄清一下:C 和 C++ 语言定义了在 x 非零时执行 if (x || y) 会发生什么 - 具体来说,y 不被评估(它不需要,因为 x是真的')。这不是“懒惰的评估”,也不是“至少在 gcc 和我的系统上”。它是用语言定义的;总是这样。
    • @jarmod 感谢您的澄清。我的错,我在这里理解错误的概念,它被称为“短路评估”,不是吗?
    • 是的,就是这样。它适用于 &&、|| 和三元运算符 ?如 (a > b) ?一个:b。
    猜你喜欢
    • 2018-09-05
    • 2021-12-05
    • 2023-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    相关资源
    最近更新 更多