0

I asked a different question about this earlier, but I was way off base about the problem so I've created a new question as I'm asking an entirely different question.

I have a function that reads a given line in a text file (given by ac variable). It performs the read of the line and then checks if that was the last line in the file. If so it increments a value.

The problem is that it's incremented the value even when it's not the actual end of the file. I think I'm using feof wrong but I've had no luck getting it to work:

int readIn(TinCan* inCan, int toggle)
  {
  int ii, isFinished = 0;
  char fullName[20];
  sprintf(fullName, "Label_%d.txt", inCan->pid);

  FILE* fp; 
    fp = fopen(fullName, "r");

    if(fp==NULL) 
      {
      printf("Error: could not open %s\n", fullName);
      }

    else
      {
      for (ii=0; ii < ((inCan->ac)-1); ii++)
        {
        fscanf(fp, "%*d %*d %*d\n"); /*move through lines without scanning*/
        }
      fscanf(fp,"%d %d %d", &inCan->ac, &inCan->state, &inCan->time);
      }

    if (feof(fp) && (toggle == 1)) 
      {
      printf("File ended"); 
      writeLog(inCan);
      isFinished = 1;
      terminated++;
      }

  fclose(fp);
  return finished;
  }

Sample data as requested, this is a text file I may use:

1 1 30
2 2 5
3 1 1

fscanf correctly assigns the values. On the second line, feof returns true and terminated is incremented. feof returns true again for the 3rd line and increments terminated a second time.

Dawson
  • 573
  • 6
  • 24
  • 2
    return finished, isFinished i think – Nick Maroulis May 19 '13 at 08:53
  • Everything I said on the other question still holds. Please provide sample file data, what you get as output, what you expect to get as output, and the return values from fscanf – xaxxon May 19 '13 at 08:54
  • 1
    Oh weird. Yeah, what @marabutt said -- if that compiles, than finished is a global variable somewhere and it's very much not what you think you're returning. Or you typo'd when copying it over to stackoverflow – xaxxon May 19 '13 at 08:55
  • 1
    There is no need to `feof(fp)` in this case because not a EOF is until you read something and then even after reading all the data. – BLUEPIXY May 19 '13 at 08:58
  • 1
    the finished variable was a copy/paste error, the variables are consistent isFinished in my code and it compiles OK. – Dawson May 19 '13 at 09:00
  • 1
    make some dummy variables inside the for loop to assign the fscanf %d values to and another one for the fscanf return value, then print them out, as well as the data from the fscanf right outside the for loop, and attach that output, please. Also, are you calling this function more than once and expecting it to continue from where it was before? – xaxxon May 19 '13 at 09:03

2 Answers2

1

feof() does not detect if the file has ended. It detects if the last read error was due to the file having ended.

feof() only happens after a failed read.

So, first read data and check the return value. If the read failed use feof() to make sure it failed because the END-OF-FILE was reached (other reasons for the read to fail are error of some kind (network down, bad sector, printer on fire, ...), detectable with ferror()).

pmg
  • 106,608
  • 13
  • 126
  • 198
  • How do I check the return value? Compare it to NULL? – Dawson May 19 '13 at 09:08
  • @Dawson by printing out the fscanf return codes like I've been asking you to for the last 30 minutes :-P – xaxxon May 19 '13 at 09:09
  • 1
    `fscanf()` returns the number of assignments executed or `EOF` in case of early END-OF-FILE or error. Use that returned value: `if (fscanf(...) != ) /* something strange */;` – pmg May 19 '13 at 09:10
  • I'm not sure how to code that. Can I use `if (fscanf(f, "%*d %*d %*d\n")==EOF)` instead? That gives me the same problems though. – Dawson May 19 '13 at 09:38
  • `fscanf(f, "%*d %*d %*d\n")` ???? Why are you trying to read 3 values into nowhere? If you want to read (and discard) a line, try `fgets()`. – pmg May 19 '13 at 09:44
  • I still don't understand why you want to test for EOF at all. If you want the fifth line you have code that will do that. – xaxxon May 19 '13 at 09:48
  • I want to know if the last line I read is the final line and the file should no longer be read. – Dawson May 19 '13 at 09:50
  • So after doing a read I put this, but it gives me a comparison between pointer and integer error. `char str[30]; if (fgets(str, 30, f)==EOF) /*check if end of file*/` – Dawson May 19 '13 at 09:50
  • `fgets()` returns a value of type `char*`; `EOF` is a value of type `int`; you're comparing values of different types and the compiler, rightfully, complains. Compare the value returned from `fgets()` with `NULL` (`NULL` is, basically, a value of type `void*` wich is compatible with any value of pointer type) rather than `EOF`. – pmg May 19 '13 at 12:39
1

It's hard to tell without knowing the data format, but

 fscanf(fp,"%d %d %d", &inCan->ac, &inCan->state, &inCan->time); 

will read 3 values, but on the last line, it won't have read the end of line character, so it's not the end of the file.

Try:

 fscanf(fp,"%d %d %d\n", &inCan->ac, &inCan->state, &inCan->time);
parkydr
  • 7,596
  • 3
  • 32
  • 42