Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected output when using fseek

Tags:

c

Assuming we have a text file named hi.txt that contains the following string:

AbCdE12345

Let say we run this code:

int main() {
  FILE *fp;
  fp = fopen("hi.txt","r");
  if(NULL == fp) { return 1; }
  fseek(fp,-1, SEEK_END);
  while (ftell(fp) > 0) {
     printf("%c",fgetc(fp));
     fseek(fp,-4, SEEK_CUR);
  }
  fclose(fp);
  return 0;
}

When I ran this code it printed: 3EbCd

When I tried to guess what it would print I thought that it should be 52d. Can anyone explain what has happened here ?

like image 968
Robert777 Avatar asked Jul 15 '13 16:07

Robert777


2 Answers

It looks like there is a non-printable end-of-line character at the end of your file. That's what gets printed first. Then the position is moved in turn to 3, E, and b. At this point, re-positioning by -3 fails, because the location would become -2. File cursor stays where it was, i.e. at C which gets printed next. The following attempt at repositioning fails too, so d gets printed. The next repositioning succeeds, terminating the loop.

To detect situations when fseek is ignored, check its return value, like this:

while (ftell(fp) > 0) {
    printf("%c",fgetc(fp));
    // Successful calls of fseek return zero
    if (fseek(fp,-4, SEEK_CUR)) {
        // Exit the loop if you can't jump back by 4 positions
        break;
    }
}
like image 79
Sergey Kalinichenko Avatar answered Nov 13 '22 11:11

Sergey Kalinichenko


For files opened in text mode the offset passed to fseek is only meaningful for values returned by ftell. So the offset may not necessarily be in bytes. Try opening the file in binary mode:

fp = fopen("hi.txt", "rb");

and see if the results are different.

like image 36
Kninnug Avatar answered Nov 13 '22 10:11

Kninnug