Thread: fgets reading the same line twice

  1. #1
    Registered User
    Join Date
    Mar 2010
    Posts
    6

    fgets reading the same line twice

    I have a piece of code that processes a file to get certain values out of it.
    Basically the input file is formatted like this:
    x y d
    (over multiple lines)
    x and y are positive integers and d is N, E, S or W.

    In my code are a few bits relating to errors. If you think they're relevent, ask, because I don't want to fill up this post with too much un-needed information.

    My code is as follows:
    Code:
    136     for(i = 1; i <= shipNumber; ++i) {
    137         if(feof(mapFile)) {
    138             return error(52);
    139         }
    140         fgets(line, 1024, mapFile);
    141         if(input_too_long(line)) {
    142             return error(52);
    143         }
    144         if(sscanf(line, "%d %d %c", &x, &y, &d) != 3) {
    145             return error(52);
    146         }
    147         switch(d) {
    148             case 'N':
    149             case 'E':
    150             case 'S':
    151             case 'W':
    152                 break;
    153             default:
    154                 return error(52);
    155         }
    156         for(j = 0; j < shipLengths[i-1]; ++j) {
    157             if((x < 0) || (x >= columns) || (y < 0) || (y >= rows)) {
    158                 return error(51);
    159             }
    160             if(map[y][x] != '0') {
    161                 return error(50);
    162             }
    163             map[y][x] = (char)i;
    164             switch(d) {
    165                 case 'N':
    166                     y--;
    167                     break;
    168                 case 'E':
    169                     x++;
    170                     break;
    171                 case 'S':
    172                     y++;
    173                     break;
    174                 case 'W':
    175                     x--;
    176             }
    177         }
    178     }
    The input file that is giving me problems is this:
    Code:
    0 0 E
    4 7 E
    5 0 E
    2 1 E 2 2 E
    EDIT: the line begining 2 1 E is the last line of the file. The board is making it look like there is a blank link on line 5 but there isn't.

    Now, this should produce an error 52, as shipNumber is 5 and there are only 4 lines in the file. What happens (I have figured out through a bunch of printf statements I put in to debug) is after the fourth line is read, the next time through the loop, feof(mapFile) returns false (should return true!) and fgets(line, 1024, mapFile) reads the fourth line again.

    What would cause my program to think it hasn't read line 4 yet?
    Last edited by lukeaar; 03-25-2010 at 01:35 AM.

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    In C arrays begin with the zero'th element, not the first. The for loop should stop at < number of items you want, not <=. That is, if I want to get 10 items, I'd use:

    Code:
    for(i = 0; i < 10; i++)
      //some code here indeces of 0 - 9 are used
    
    not
    
    for(i = 1; i <= 10; i++) 
      //indeces of 1 to 10 are used. 10 is outside the array of ten items
    feof() may not do just what you'd think it should do, also. Typically repeating the last line, a second time. Does that sound familiar?

    This is preferred:

    Code:
    while((fgets(buffer, sizeof(buffer), filePointer)) != NULL) {
      (your other code, in here)
    }

  3. #3
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Alluded to by Adak, this is a problem:
    Code:
    for(i = 1; i <= shipNumber; ++i) {
        if(feof(mapFile)) {
            return error(52);
        }
        fgets(line, 1024, mapFile);
    EOF is not set until after an attempt to read past the end of the file occurs. This means that after you've read/processed the last line EOF is still false although you are at the physical end of the file. Because of this, when you reenter the loop after processing that last line, the feof test returns false since you haven't yet attempted to read past that point. Therefore your code proceeds to attempt a read action through fgets and at this point you're committed to processing data since you're already in the loop. The fgets call fails (at this point feof would return true) and the buffer "line" remains unchanged. The net effect of this is that you process the last line in the file twice.

    Some simple solutions would be to either put the feof test immediately after the fgets call instead of before it, or to test the return result of the fgets call for failure.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  4. #4
    Registered User
    Join Date
    Mar 2010
    Posts
    6
    Thank you very much. I just put feof after the fgets and it works great now.

    Thanks for the help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Ignoring line in C++ when reading from file
    By falzone in forum C++ Programming
    Replies: 7
    Last Post: 11-16-2007, 12:08 AM
  2. fgets is not reading properly
    By joeprogrammer in forum C Programming
    Replies: 5
    Last Post: 02-20-2006, 09:58 AM
  3. reading a file line by line and char *
    By odysseus.lost in forum C Programming
    Replies: 8
    Last Post: 05-31-2005, 09:47 AM
  4. Skipping 2 next line when reading in from file?
    By aspand in forum C++ Programming
    Replies: 4
    Last Post: 03-21-2003, 10:22 AM
  5. line reading problem
    By papous in forum C Programming
    Replies: 2
    Last Post: 11-22-2001, 12:29 PM