Hey guys,
I have a silly issue that is bothering me. I am trying to read an unknown amount of lines from an input file and basically stop when I reach the EOF. I probably does'nt matter but the assignment is to create a simple lexical analyzer/scanner for a mini-subset of Pascal. Long story short, I need to read character at a time until either my buffer is full or I reach the end-of-line symbol. Because I have gone so far in my program, many of my functions a designed to rely on the inclusion of '\n' at the end of my buffer. Here is some code that will maybe assist you in understanding what I mean

Line ReadFile(FILE *in)
{
     struct Line inputLine;
     int loopControl=0;
     char c;

    //reading data into buffer
    c = fgetc(in);

    if( (int)c == 10 )
        c=fgetc(in);

    while(loopControl < 80 && (int)c != 13)  
    {
       if((int) c == 10)
       {
                 inputLine.lineArray[loopControl]= c;
                 loopControl= loopControl + 1;
                 break;      
       }                  
       inputLine.lineArray[loopControl]= c;
       c = fgetc(in);                     
       loopControl=loopControl + 1;    

    }//end of while loop  

    //setting the actual size of the array
    inputLine.lineArraySize = loopControl;
    return inputLine;
}

The structure Line looks like this:

struct Line
{
       char lineArray[80];
       int lineArraySize;
};

The problem is that I read everything in the file correctly, but when I get to the last line in the file the data on that line is skipped. This is true if I use a looping mechanism something like this:

 while( feof(inputFile)==0  )
 {
    bufferInput= ReadFile(inputFile);// read a buffer-worth of data from input file
    clearBuffer(noCommentBuffer);//JUST CLEARS BUFFER.

 }

and if I try to modify the looping mechanism to control the reading process to something like the following it will read the last line of data but it will not properly fill the data in the buffer.

 bufferInput= ReadFile(inputFile);// read a buffer-worth of data from input file
 while( feof(inputFile)==0  )
 {
    //process data
    clearBuffer(noCommentBuffer);//JUST CLEARS BUFFER.
    bufferInput= ReadFile(inputFile);// read a buffer-worth of data from input file
 }

Can anyone please help me. This scanne project is hard in general, but I understand it. This I/O stuff in C I am not getting.
Thanks for any advise
Alex

Do NOT use feof() - it simply doesn't work the way a human thinks it should, and it will goof you up every time.

There are three ways:

1)

while((fgets(myCharArray, sizeof(myCharArray), filePointer)) != NULL) {
   //your code to work with myCharArray[], as you need to
   //fgets always puts a newline at the end of the array for you, space permitting
   //and NEVER overflows your char array. sscanf() is well suited to be used now.
}

2)

while((fscanf(filePointer, "%[^\n]", myCharArray)) > 0) {
   //similar to fgets() above. Reads and stores until the newline
   //as long as as it's able to read and store at least one object (not OOP though)
}

3)

int ok;  //NOT char, int!

while((ok=getchar()) != EOF) {
   //now you're forced to work at the char by char 
   //level, which is usually rather tedious
}

Overall, I'd use fgets() probably. It allows you to scan and find and parse our the char array as many times as you need to, very easily. Be sure to give it a generous size so you'll always have the entire line of text, + the newline + the end of string char: '\0'. To get rid of the newline at the end of the char array:

char *ptr = myCharArray;
ptr=strchr(myCharArray, '\n');
if(ptr)
   *ptr='\0';

fscanf(filePointer, "%[^\n]", myCharArray)

As an aside, this is no better than gets(). you can fix it by providing a field width though:

char myCharArray[100];
fscanf(filePointer, "%99[^\n]", myCharArray);

This ensures that fscanf() will never write more characters than the array can hold (99 "real" characters, plus a null character at the end). However, it can be problematic if you use something like BUFSIZ for the array size because it's not as simple as just throwing a literal value into the field width. You can kind of cheat it in the case of macros using a stringizing macro:

#include <stdio.h>

#define STR_VAL(x) #x
#define STR(x)     STR_VAL(x)

#define SIZE 10

int main(void)
{
    char line[SIZE + 1];

    printf("Format string: '%s'\n", "%" STR(SIZE) "[^\\n]");

    fputs("Please enter a line: ", stdout);
    fflush(stdout);

    if (scanf("%" STR(SIZE) "[^\n]", line) == 1) {
        printf("'%s'\n", line);
    }

    return 0;
}

But the more general method is generating the format string at runtime with sprintf():

#include <stdio.h>

int main(void)
{
    char fmt[1024];
    char line[10];

    sprintf(fmt, "%%%d[^\\n]", sizeof(line) - 1);
    printf("Format string: '%s'\n", fmt);

    fputs("Please enter a line: ", stdout);
    fflush(stdout);

    if (scanf(fmt, line) == 1) {
        printf("'%s'\n", line);
    }

    return 0;
}

The benefit of this is you can use sizeof or any variable to get the size of the array rather than rely on macro repetition, just like fgets(). But that raises the question of if you're going to all of this trouble to simulate fgets(), why not just use fgets()? ;)

Edited 3 Years Ago by deceptikon

This article has been dead for over six months. Start a new discussion instead.