【问题标题】:How to compare 2 files lexicographically using C如何使用C按字典顺序比较2个文件
【发布时间】:2010-09-28 09:54:15
【问题描述】:

大家好,我目前正在尝试使用 C 实现一个函数,该函数将两个文件名作为命令行参数并按字典顺序进行比较。

如果第一个文件的内容小于第二个文件的内容,该函数将返回 -1,如果第二个文件的内容小于第一个文件的内容,则返回 1,如果文件小于第二个文件的内容,则返回 0。一模一样。

请给我一些建议,告诉我应该如何开始。

[编辑]

大家好,如果问题中有任何不清楚的部分,我很抱歉,所以我将在此处发布问题的链接:Original question。事情是它是一个 uni 赋值,所以我们应该只使用基本的 C 属性来完成它,可能只包括 stdio.h、stdlib.h 和 string.h。对造成的麻烦深表歉意。这也是我已经拥有的代码,我现在的主要问题是该函数不知道 file1.txt(请参阅链接)的第一行比 file2.txt 长,但实际上在字典上更少:

int filecmp(char firstFile[], char secondFile[])
{
    int similarity = 0;
    FILE *file1 = fopen(firstFile, "r");
    FILE *file2 = fopen(secondFile, "r");
    char line1[BUFSIZ];
    char line2[BUFSIZ];

    while (similarity == 0)
    {
        if (fgets(line1, sizeof line1, file1) != NULL)
        {
            if (fgets(line2, sizeof line2, file2) != NULL)
            {
                int length;

                if (strlen(line1) > strlen(line2))
                {
                    length = strlen(line1);
                }
                else
                {
                    length = strlen(line2);
                }

                for (int i = 0; i < length; i++)
                {
                    if (line1[i] < line2[i]) similarity = -1;
                    if (line1[i] > line2[i]) similarity = 1;
                }
            }
            else
            {
                similarity = 1; //As file2 is empty
            }
        }
        else
        {
            if (fgets(line2, sizeof line2, file2) != NULL)
            {
                similarity = -1; // As file1 is empty
            }
            else break;
        }
    }

    fclose(file1);
    fclose(file2);

    return similarity;
}

[结束编辑]

非常感谢,
乔纳森·蔡

【问题讨论】:

  • 抱歉我这么无知,你说的字典顺序是什么意思? (以及在您的上下文中“更少”或“更多”是什么意思)

标签: c


【解决方案1】:

查看 UNIX cmp 实用程序的源代码,例如here。相关文件为regular.c。如果不能使用mmap,通过fgetc()实现的原理是一样的:只要比较相同,就从两个文件的每一个中读取一个字符。当(如果!)您发现差异时,返回比较结果。一个文件是另一个文件的正确前缀(例如“ABC”“ABCCC”)的边界情况可以通过将 EOF 视为无限小的值来解决。这已经在 C 中巧妙地解决了,因为fgetc() 保证仅在 EOF 上返回负值;正确的字符是&gt;= 0

【讨论】:

  • 嘿抱歉,但我认为我没有完全理解你的解释。但是据我所知,您是说每次为每个文件遍历一个字符并比较它们,并且不用担心 EOF,因为它已经由 fgetc 处理,当它发生时会返回一个负值,对吗?如果是这种情况,它与我所做的非常相似,只是当文件按字典顺序较小但第一行较长时,它不能解决问题。抱歉,如果我对您的解释有任何错误的解释。
【解决方案2】:

你可以使用 strcmp 吗?

如果是这样(未经测试):

int ret = 0;
while (ret == 0)
{ 
    char line1 [ MAX_LINE_LEN ]; 
    char line2 [ MAX_LINE_LEN ]; 
    if (fgets(line1, MAX_LINE_LEN, file1) != NULL )
    {
        if (fgets(line2, MAX_LINE_LEN, file2) != NULL )
        {
            ret = strcmp(line1, line2);
        }
        else
        {
            ret = 1;
        }
    }
    else
    {
        if (fgets(line2, MAX_LINE_LEN, file2) != NULL )
        {
            ret = -1;
        }
        else
        {
            break;
        }
    }
}
return ret;

【讨论】:

  • 我认为他的意思是逐字节比较。
  • 我现在已经对此进行了测试,它确实适用于我尝试过的测试用例。
  • @zvrba:如果一个文件没有在另一个文件之前终止,这就是 strcmp 行的作用。
  • 你快到了;将fgets(line,LEN,file) 替换为fread(buf,1,LEN,file),并使用memcmp(buf1,buf2,LEN) 代替strcmp()。啊,不要忘记在读取之前将填充缓冲区归零,或者至少在fread()返回的位置添加一个零。
  • 使用基于行的缓冲区,意味着短行将比长行比较“少”,即使它有一个 0x03 而另一行有换行符。您的方法仅对纯 ASCII 文件有效
猜你喜欢
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多