简体   繁体   中英

Why does fgetc move the file position indicator backwards?

A program that runs just fine on my freeBSD system fails when I build it on windows (Visual Studio 15). It goes into an endless loop here:

//...
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;
    }
}
//...

On closer look (by adding a bunch of fgetpos()-calls) I find that fgetc moves the file position indicator backwards . So it misses the beginning of the file and some '@' if they are not in a multiple-of-3 position from the end.

I notice that this only happenes when the file f is opened with

fopen(filename, "a+");
//text mode read/append

When I change it to

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

then everything works as expected. I think for my code it is safe just to use binary mode all the time. But two questions remain:

  • Are there reasons that stand against binary mode?
  • What trickery is this with wrong direction in text mode?

Quoting C11 7.21.9.2 the fseek function:

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.

Invoking fseek with a whence argument of SEEK_CUR on a stream open in text mode is not covered by the C Standard. Opening the file in binary mode seems a much better option.

The value returned by fgetpos() may not be meaningful as an offset in the file, it is only meant to be passed as an argument to fsetpos() .

As a general remark, you should try and change you algorithms to avoid relying on backwards seeks in the stream, especially relying on fseek() errors seems unreliable. Instead save the position before the fgetc() with ftell() or fgetpos() and restore it when needed with fseek(pos, SEEK_SET, fp) or fsetpos() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM