【问题标题】:Infinite loop while trying to read from file尝试从文件中读取时出现无限循环
【发布时间】:2012-10-27 15:05:58
【问题描述】:

我想从文件中读取字节然后重写它们。 我确实喜欢这样:

FILE *fp;
int cCurrent;
long currentPos;

/* check if the file is openable */
if( (fp = fopen(szFileName, "r+")) != NULL )
{
    /* loop for each byte in the file crypt and rewrite */
    while(cCurrent != EOF)
    {
        /* save current position */
        currentPos = ftell(fp);
        /* get the current byte */
        cCurrent = fgetc(fp);
        /* XOR it */
        cCurrent ^= 0x10;
        /* take the position indicator back to the last position */
        fseek(fp, currentPos, SEEK_SET);
        /* set the current byte */
        fputc(cCurrent, fp);
    }

对文件执行代码后,文件的大小在无限循环中增加。

我的代码有什么问题?

【问题讨论】:

  • 您应该在写入 (fputc()) 之后和下一次读取 (fgetc()) 之前执行 fseek(),即使它只是 fseek(fp, 0L, SEEK_CUR);。在更新流上,应该在读取和写入之间的每次更改之间进行类似搜索的操作。
  • @JonathanLeffler 为什么我必须进行 fseek?
  • 因为 C 标准说如果你不这样做,行为是未定义的。未定义行为的危险之处在于它可能会在当前系统上执行您所期望的操作,但是如果编译器(或库)发生更改,或者您移动到另一台机器上,那么曾经工作的程序可能会停止工作 - 并且两种实现都完全正确。
  • ISO/IEC 9899:2011, §7.21.5.3 fopen 函数。 ¶7 当文件以更新模式打开时(“+”作为上述模式参数值列表中的第二个或第三个字符),可以在关联的流上执行输入和输出。但是,如果没有对fflush 函数或文件定位函数(fseekfsetposrewind)的介入调用,则输出不应直接跟在输入之后,并且输入不应直接跟在输出之后没有对文件定位函数的干预调用,除非输入操作遇到文件结尾。
  • @JonathanLeffler 谢谢你的解释!

标签: c file fopen infinite-loop


【解决方案1】:

你是XOR-ing cCurrent0x10,即使它等于EOF。一旦你XOR,它就不再是EOF,所以你的循环永远不会终止。

使循环无限,当你看到EOF时从中间退出,像这样:

for (;;)  {
    /* save current position */
    currentPos = ftell(fp);
    /* get the current byte */
    if ((cCurrent = fgetc(fp)) == EOF) {
        break;
    }
    /* XOR it */
    cCurrent ^= 0x10;
    /* take the position indicator back to the last position */
    fseek(fp, currentPos, SEEK_SET);
    /* set the current byte */
    fputc(cCurrent, fp);
    /* reset stream for next read operation */
    fseek(fp, 0L, SEEK_CUR);
}

【讨论】:

  • 建议在 if (cCurrent = fgetc(fp) == EOF) { 中的赋值周围加上括号,否则它将无法正常工作。
  • @DanielFischer 非常感谢,你说的完全正确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-07
  • 2021-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多