4

my question is simple, but I can't find it on google, so here I am.

Basically, as an example, I am reading in a bunch of integers until EOF from an input file. I used fgetc to check, but then it moves the file pointer to the address of the 2nd integer. How can I check for EOF in this while loop without moving the file pointer when it checks?

Keep in mind I will be doing something much more complex with this loop than scanning in integers. Also, don't mention my use of fscanf rather than fgets, I know. Its just a simple example to show you what I mean.

while(fgetc(ifp) != EOF)
{

    fscanf(ifp, "%d", &test);
    printf("%d\n", test);
}

If the input file has integers 1-10 for example, the above code would print:

2 3 4 5 6 7 8 9 10

Missing the 1!

Karim Elsheikh
  • 349
  • 3
  • 6
  • 18

6 Answers6

7

fgetc Returns the character currently pointed by the internal file position indicator of the specified stream. The internal file position indicator is then advanced to the next character.Using do{ }while(); will solve your problem.

Dayal rai
  • 6,548
  • 22
  • 29
  • because it is `do{}while();` which performs first and tests later. – Dayal rai Aug 05 '13 at 05:41
  • keep in mind that the call to `fgetc()` will gobble up one of the whitespace characters separating the integers; while it does work. this smells iffy to me... – Christoph Aug 05 '13 at 05:50
6

You should consider EOF conditions to be an implementation detail. What's really important here is whether fscanf has successfully returned a value.

while(fscanf(ifp, "%d", &test) == 1) {
    printf("%d\n", test);
}

On the other hand, this feels like one of those times where it makes sense to put the logic in the middle of the loop.

while(1) {
    int ret = fscanf(ifp, "%d", &test);
    if (ret != 1)
        break;
    printf("%d\n", test);
}

Especially for debugging, it can be nice to split things up into separate statements with variables that can be inspected.

luser droog
  • 18,988
  • 3
  • 53
  • 105
3

For various reasons, it's impossible to determine if EOF has been reached without actually performing a prior read from the file.

However, using a seperate function call to do this is a bad idea, even if you were to use ungetc() to put back the character you tried to read.

Instead, check the return value of the call to fscanf() itself:

while(fscanf(ifp, "%d", &test) == 1)
{
    printf("%d\n", test);
}
Christoph
  • 164,997
  • 36
  • 182
  • 240
3

How about simply:

while (fscanf (ifp, "%d", &test) != EOF)
    printf("%d\n", test);
verbose
  • 7,827
  • 1
  • 25
  • 40
2

fgetc(ifp) advance the file pointer, hence skipping your first integer

Instead Use: -

while(1)
{

    if(fscanf(ifp, "%d", &test)!=1) 
         break;
    printf("%d\n", test);
}
P0W
  • 46,614
  • 9
  • 72
  • 119
  • No, check [this](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong) – David Ranieri Aug 05 '13 at 05:33
  • @DavidRF check the context of that, OP case is not too specific – P0W Aug 05 '13 at 05:37
  • `while(!feof(ifp))` it's wrong because (in the absence of a read error) it enters the loop one more time than the author expects. If there is a read error, the loop never terminates. – David Ranieri Aug 05 '13 at 05:39
  • Could you give me an example of a read error that would cause an infinite loop? I'm just curious. – Karim Elsheikh Aug 05 '13 at 05:42
  • Now your code is not buggy, but `feof` makes no sense: **his indicator is generally set by a previous operation on the stream that attempted to read at or past the end-of-file**, simply use `while(fscanf(...) == 1)` – David Ranieri Aug 05 '13 at 06:03
0

The real answer is to use feof

https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.bpxbd00/feof.htm

Samie Bencherif
  • 1,285
  • 12
  • 27