使用fseek
回溯字符fscanf
操作是否可靠?
例如,如果我只有fscanf
- 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
答案 0 :(得分:8)
您正在看到“文本”和“二进制”文件之间的区别。当以文本模式打开文件时(fopen第二个参数中没有'b'),stdio库可能(实际上必须)根据操作系统对文本文件的约定来解释文件的内容。例如,在Windows中,一行以\ r \ n结尾,并且由stdio将其转换为单个\ n,因为这是C约定。写入文本文件时,单个\ n输出为\ r \ n。
这使得编写处理文本文件的可移植C程序变得更加容易。然而,一些细节变得复杂,而fseeking就是其中之一。因此,在一些情况下,C标准仅在文本文件中定义fseek:从最开始,到最后,到当前位置,以及用ftell检索的先前位置。换句话说,您无法计算要搜索文本文件的位置。或者你可以,但你必须自己处理所有平台特定的细节。
或者,您可以使用二进制文件并自行进行行结束转换。再次,可移植性受到影响。
在你的情况下,如果你只想回到你上次fscancf的地方,最简单的就是在fscanf之前使用ftell。
答案 1 :(得分:2)
这是因为fseek使用字节,而fscanf智能地处理回车符和换行符是两个字节,并将它们作为一个字符吞并。
答案 2 :(得分:1)
Fseek不了解文件的内容,只是将文件指针移回10个字符。
fscanf取决于操作系统,可以不同地解释换行符;如果你在DOS上并且^ M没有出现在文件中,fscanf甚至可能会插入^ M.查看C编译器附带的手册
答案 3 :(得分:1)
刚刚尝试使用VS2008,发现fscanf和fseek以相同的方式处理CR和LF字符(作为单个字符)。
所以有两个文件:
<00> 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。
这似乎是一个特定于操作系统/编译器的问题。
答案 4 :(得分:0)
您是否测试过fscanf
的返回值?发布一些代码。
看看ungetc
。你可能需要对它进行循环。