c - 为什么 fgetc 将文件位置指示器向后移动?

标签 c visual-studio fopen fgetc

在我的 freeBSD 系统上运行良好的程序在 Windows (Visual Studio 15) 上构建时失败。它在这里进入无限循环:

//...
while (1) {
    if ('@' == fgetc(f)) {
        // we do some stuff here. irrelevant for stackoverflow question
        break;
    }        
    fseek(f, -1, SEEK_CUR);        
    if (0 != fseek(f, -1, SEEK_CUR)) {
        // Beginning of file.
        break;
    }
}
//...

仔细观察(通过添加一堆 fgetpos() 调用)我发现 fgetc 将文件位置指示器向后 移动。所以它会错过文件的开头和一些 '@',如果它们不在末尾的 3 的倍数位置。

我注意到这只有在用

打开文件 f 时才会发生
fopen(filename, "a+");
//text mode read/append

当我把它改成

fopen(filename, "ab+");
//binary mode read/append

然后一切都按预期工作。 我认为对于我的代码来说,一直使用二进制模式是安全的。 但是还有两个问题:

  • 是否有反对二进制模式的理由?
  • 在文本模式下方向错误是什么诡计?

最佳答案

引用 C11 7.21.9.2 fseek 函数:

For a text stream, either offset shall be zero, or offset shall be a value returned by an earlier successful call to the ftell function on a stream associated with the same file and whence shall be SEEK_SET.

在以文本模式打开的流上使用 SEEK_CUR 的 whence 参数调用 fseek 未包含在 C 标准中。以二进制模式打开文件似乎是一个更好的选择。

fgetpos() 返回的值作为文件中的偏移量可能没有意义,它只是作为参数传递给 fsetpos()

作为一般性评论,您应该尝试更改算法以避免依赖流中的向后查找,尤其是依赖 fseek() 错误似乎不可靠。而是使用 ftell()fgetpos() 保存 fgetc() 之前的位置,并在需要时使用 fseek(pos , SEEK_SET, fp)fsetpos()

关于c - 为什么 fgetc 将文件位置指示器向后移动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35848744/

相关文章:

c - 从文件读取字符串时出错

c - 如何为您的程序分配更多内存(GCC)

python - pip 可以与 Visual Studio 中的 Python 工具一起使用吗?

c++ - 多个项目引用 MFC : "use mfc in a static library" vs "use mfc in a shared dll"?

excel - 运行excel工作簿时出现"value does not fall within the expected range"

c - 如何在c中使用数组打开文件

通过索引的距离更改数组的值 (c)

c - 优化线段树的范围最大查询?

无法使用 fopen() 打开文件

c++ - fopen() 在打开数百次后无法正常工作是否有原因?