使用fseek回溯

使用fseek来回溯字符fscanf操作是否可靠?

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

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

为什么会这样?

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

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

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

或者,您可以使用二进制文件并自行执行行结束转换。 同样,可移植性受到影响。

在你的情况下,如果你只想回到你最后做fscancf的地方,最简单的就是在fscanf之前使用ftell。

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

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

fscanf取决于操作系统,可以不同地解释换行符; 如果你在DOS上并且^ M没有出现在文件中,fscanf甚至可能会插入^ M. 查看C编译器附带的手册

刚刚尝试使用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。

这似乎是一个非常OS /编译器特定的问题。

你测试了fscanf的返回值吗? 发布一些代码。

看看ungetc 。 您可能必须在其上运行循环。