15

fopen问:我正在尝试通过使用mode 、读取某个字符串并写回修改后的字符串来就地更新文件"r+",但它不起作用。

A:一定要fseek在你写之前调用,既要回到你试图覆盖的字符串的开头,又因为在读/写“+”模式下读和写之间总是需要一个fseek 或。fflush

我的问题是为什么 fseekfflush总是需要在读/写“+”模式下读写之间?Andrew Koenig 的 C Traps and Pitfalls (1989) 第 5.2 节提到这是因为向后兼容问题。谁能详细解释一下?

4

3 回答 3

16

缓冲输入和输出操作。查看setvbuf()该功能的_IOFBF,_IOLBF参数。

fseek()fflush() 要求库提交缓冲操作。

该标准将查找或刷新操作指定为强制性的,以允许库使用一些快捷方式;否则,对于每个 I/O 操作,lib 必须检查前一个操作是否也是读取操作(或写入操作),并在 I/O 的“方向”发生变化时自行触发刷新。使用原样的规范,库可以假设客户端在更改 I/O 方向之前进行了查找/刷新。

于 2009-11-11T08:43:14.133 回答
5

因为它使操作系统/库代码更简单。文件流可能有单独的读取写入缓冲区,并且需要额外的努力来确保它们始终同步。在不需要的时候,这会降低性能。

因此,程序员需要在需要时明确地执行此操作。

于 2009-11-11T08:44:16.900 回答
5

阅读 Plauger 的“标准 C 库”,了解 (C89) 标准库的各种特性为何如此,尤其是标准 I/O 库的某些部分为何如此。一个原因是 C 运行在非常多样化的系统和不同的媒体上。磁带等设备的处理方式可能与您习惯认为的磁盘驱动器有所不同。此外,在 Unix 上,考虑您的“tty”设备——它将键盘和鼠标连接到屏幕——三种完全不同的硬件。这些之间的协调已经够棘手了。标准中的规则使它更容易。


请注意,标准规定了这一点。这是来自 C11 标准 ISO/IEC 9899:2011,但在之前的版本中措辞相似:

§7.21.5.3fopen功能

¶7 当文件以更新模式打开时(“+”作为上述模式参数值列表中的第二个或第三个字符),可以在关联的流上执行输入和输出。但是,如果没有对函数fflush或文件定位函数(fseekfsetposrewind输入操作遇到文件结尾。在某些实现中,使用更新模式打开(或创建)文本文件可能会打开(或创建)二进制流。

于 2009-11-11T08:47:04.110 回答