5

使用fseek回溯字符fscanf操作可靠吗?

例如,如果我刚刚fscanf-ed 10 个字符,但我想回溯 10 个字符,我可以fseek(infile, -10, SEEK_CUR)吗?

在大多数情况下,它都有效,但我似乎对角色有问题^M。显然fseek将其注册为 char 但fscanf不注册它,因此在我之前的示例中^M,需要一个包含 a 的 10 char 块fseek(infile, -11, SEEK_CUR)fseek(infile, -10, SEEK_CUR)会使它缩短 1 个字符。

为什么会这样?

编辑:我fopen在文本模式下使用

4

5 回答 5

8

您会看到“文本”和“二进制”文件之间的区别。当以文本模式打开文件时(在 fopen 第二个参数中没有“b”),stdio 库可能(实际上,必须)根据操作系统对文本文件的约定来解释文件的内容。例如,在 Windows 中,一行以 \r\n 结尾,而这会被 stdio 转换为单个 \n,因为这是 C 约定。写入文本文件时,单个 \n 将输出为 \r\n。

这使得编写处理文本文件的可移植 C 程序变得更加容易。然而,一些细节变得复杂,fseeking 就是其中之一。正因为如此,C 标准只在少数情况下在文本文件中定义 fseek:到最开始、到最后、到当前位置,以及到使用 ftell 检索到的先前位置。换句话说,您无法计算要查找文本文件的位置。或者你可以,但你必须自己处理所有特定于平台的细节。

或者,您可以使用二进制文件并自己进行行尾转换。同样,便携性受到影响。

在您的情况下,如果您只想回到上次执行 fscancf 的位置,最简单的方法是在 fscanf 之前使用 ftell。

于 2009-04-23T05:33:25.243 回答
2

这是因为 fseek 使用字节,而 fscanf 智能地处理回车和换行是两个字节,并将它们作为一个字符吞下。

于 2009-04-23T04:41:54.257 回答
1

Fseek 不了解文件的内容,只是将文件指针向后移动 10 个字符。

fscanf 取决于操作系统,可能会以不同的方式解释换行符;如果您在 DOS 上并且 ^M 未出现在文件中,甚至可能 fscanf 将插入 ^M。检查 C 编译器附带的手册

于 2009-04-23T04:38:14.267 回答
1

刚刚用 VS2008 试过这个,发现 fscanf 和 fseek 以相同的方式处理 CR 和 LF 字符(作为单个字符)。

所以有两个文件:

0000000: 3132 3334 3554 3738 3930 3132 3334 3536 12345X7890123456

0000000: 3132 3334 350d 0a37 3839 3031 3233 3435 12345..789012345

如果我读取了 15 个字符,我会找到第二个“5”,然后再寻找 10 个字符,我读取的下一个字符是第一种情况下的“X”和第二种情况下的 CRLF。

这似乎是一个非常特定于操作系统/编译器的问题。

于 2009-04-23T04:48:31.417 回答
0

您是否测试了 的返回值fscanf?贴一些代码。

看看ungetc。您可能必须在它上面运行一个循环。

于 2009-04-23T05:32:36.693 回答