Fputs returns -1 after reading to the end of the file

I am having problems writing file errors on Windows. I simplified it to this example:

FILE* f = fopen("test.out", "r+b"); fseek(f, -1, SEEK_END); // one byte before the end printf("read byte: %c\n", fgetc(f)); // read the last byte; now at the end printf("attempting write: %d\n", fputs("text", f)); 

This correctly outputs the last byte of test.out , but fputs fails and returns -1. These similar examples work fine:

  • Do not read

     FILE* f = fopen("test.out", "r+b"); fseek(f, 0, SEEK_END); // this is where I ended up after the fgetc() above printf("attempting write: %d\n", fputs("text", f)); 
  • Look to the end after reading (although we are already there)

     FILE* f = fopen("test.out", "r+b"); fseek(f, -1, SEEK_END); printf("read byte: %c\n", fgetc(f)); fseek(f, 0, SEEK_END); printf("attempting write: %d\n", fputs("text", f)); 
  • Search for exactly where we are already

     FILE* f = fopen("test.out", "r+b"); fseek(f, -1, SEEK_END); printf("read byte: %c\n", fgetc(f)); fseek(f, ftell(f), SEEK_SET); printf("attempting write: %d\n", fputs("text", f)); 
  • Read, but not the last byte

     FILE* f = fopen("test.out", "r+b"); fseek(f, -2, SEEK_END); // two bytes before the end printf("read byte: %c\n", fgetc(f)); // read the penultimate byte printf("attempting write: %d\n", fputs("text", f)); 
  • Read the end (...)

     FILE* f = fopen("test.out", "r+b"); fseek(f, -1, SEEK_END); // one byte before the end printf("read byte: %c\n", fgetc(f)); // read the last byte; now at the end printf("read byte: %c\n", fgetc(f)); // read a garbage byte printf("attempting write: %d\n", fputs("text", f)); 

All this indicates a stream error or an eof problem, but ferror(f) and feof(f) both return 0 until fputs() . After, ferror(f) is nonzero, but errno is 0, so I don't know what the problem is

I see this only on Windows, both in Visual Studio 2008 and in GCC 4.7.2 (MinGW). On Linux, the same code works without errors

+4
source share
1 answer

Standard C requires you to perform a search when switching from read mode to write mode, or vice versa, with the exception of some other special cases that are usually not worth listing.

An implementation (such as I wrote many years ago for BSD or Linux) may be more forgiving than required, making your code "just working." (This is very simple, you just need to save two separate counters as part of the implementation instead of one combined counter.) But the standard does not require the implementation to be friendly, but Windows does not.

+6
source

Source: https://habr.com/ru/post/1486102/


All Articles