【问题标题】:Is this not the same logic? Different Results这不是同一个逻辑吗?不同的结果
【发布时间】:2014-07-23 22:15:21
【问题描述】:

我不明白这两个代码如何给我不同的结果?

1

int main()
{

    struct stat buf1;
    struct stat buf2;
    
    FILE *fp1, *fp2;
    int ch1, ch2;
    clock_t elapsed;
    char fname1[40], fname2[40];

    printf("Enter name of first file:");
    fgets(fname1, 40, stdin);
    while (fname1[strlen(fname1) - 1] == '\n')
    {
        fname1[strlen(fname1) -1] = '\0';
    }

    printf("Enter name of second file:");
    fgets(fname2, 40, stdin);
    while (fname2[strlen(fname2) - 1] == '\n')
    {
        fname2[strlen(fname2) -1] = '\0';
    }

    fp1 = fopen(fname1, "r");
    if (fp1 == NULL)
    {
        printf("Cannot open %s for reading\n", fname1);
        exit(1);
    }

    fp2 = fopen(fname2, "r");
    if (fp2 == NULL)
    {
        printf("Cannot open %s for reading\n", fname2);
        exit(1);
    }

    stat(fname1, &buf1);
    size_t size1 = buf1.st_size;

    stat(fname2, &buf2);
    size_t size2 = buf2.st_size;

    printf("Size of file 1: %zd\n", size1);
    printf("Size of file 2: %zd\n", size2);

    elapsed = clock(); // get starting time

    size_t smallest = 0;

    if(size1 < size2)
    {
        smallest = size1;
    }
    else
    {
        smallest = size2;
    }

    int i;

    unsigned long long counter = 0;

    ch1 = getc(fp1);
    ch2 = getc(fp2);

    for(i = 0; i < smallest; i++)
    {       
        ch1 = getc(fp1);
        ch2 = getc(fp2);

        if((ch1 ^ ch2) == 0)
        {
            counter++;
        }
    }
    
    fclose (fp1); // close files
    fclose (fp2);

    float percent = (float)counter / (float)smallest * 100.0f ;

    printf("Counter: %u Total: %u\n", counter, smallest);
    printf("Percentage: %.2f%\n", percent);

    elapsed = clock() - elapsed; // elapsed time
    printf("That took %.2f seconds.\n", (float)elapsed/CLOCKS_PER_SEC);
    return 0;
}

2

... 

   
    ch1  =  getc(fp1); // read a value from each file
    ch2  =  getc(fp2);

    while(1) // keep reading while values are equal or not equal; only end if it reaches the end of one of the files
    {
        ch1 = getc(fp1);
        ch2 = getc(fp2);
        
        if((ch1 ^ ch2) == 0)
        {
            counter += 1;
        }
   
        total += 1;

        if ( ( ch1 == EOF) || ( ch2 == EOF)) // if either file reaches the end, then its over!
        {
            break; // if either value is EOF
        }
    }
  
    fclose (fp1); // close files
    fclose (fp2);

    float percent = (float)counter / (float)total * 100.0f ;

    printf("Counter: %u Total: %u\n", counter, total);
    printf("Percentage: %.2f%\n", percent);

    elapsed = clock() - elapsed; // elapsed time
    printf("That took %.4f seconds.\n", (float)elapsed/CLOCKS_PER_SEC);
    return 0;
}

第二个代码给了我更高的复制结果??他们不应该是一样的吗?只有一个更有效率。我通过添加并行性使用 Xeon Phi 运行第一个代码,但首先,我希望两个代码具有相同的重复率。

【问题讨论】:

  • BTW 第一个数据被丢弃。
  • 它们看起来等价,但 FWIW,if ((ch1 ^ ch2) == 0) 可以在两段代码中替换为 if (ch1 == ch2)A xor B 仅在 A == B 时为 0。
  • 看起来你没有得到 size1 size2 正确。
  • 要调试这个,你可以打印更多,例如countsmallesttotal 等,以找出问题所在。 smallest 应与 total 相同。这两个值也可以手动与实际文件大小进行比较。
  • 代码存在一些问题。在这两个示例中,每个文件的第一个字节的比较都被忽略了。然而,最大的问题是 stat 返回磁盘上的分配(块大小的倍数),而第二个在尝试读取文件末尾后停止。 EOF 的检查应该在相等性检查之前。

标签: c file for-loop io while-loop


【解决方案1】:

明显的区别是 2 在读取 EOF 时会停止,而 1 不会。实际上,2 计数 +1,然后在读取 EOF 时停止。您应该在增加计数器之前执行EOF 检查。

如果您更新 1 以同时检查 EOF,您可能会发现相同的结果。

还不清楚为什么在每个循环开始之前从每个文件中读取并丢弃一个字符。

也许您忽略了st_size 可能与可读字节数不对应,尤其是当您将文件作为文本流打开时。 (例如,在 Windows 中,st_size 会将 CR-LF 计为两个,但 getc 只会得到 \n)。

您可以尝试以二进制模式打开文件 ("rb")。此外,在 2 的情况下实际查看 total 的值(并报告哪个文件命中 EOF)可能会很有启发性。

【讨论】:

  • 太棒了,感谢关闭一个字节的错误,我将尝试将其作为二进制文件读取
【解决方案2】:

通过检查if((ch1 ^ ch2) == 0),您不计算重复,您可以改用if(ch1 == ch2)

【讨论】:

  • 但那将是比较地址而不是字节,我想比较字节
  • 其实 if(ch1 == ch2) 是比较字节,不涉及地址。
猜你喜欢
  • 2018-09-06
  • 1970-01-01
  • 2021-04-29
  • 2016-10-18
  • 2019-01-31
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 2022-12-03
相关资源
最近更新 更多