0
votes

I have a txt file with words and number separated by commas. I want to read in characters until the next comma, process the data and then continue to read from the location where the last comma was found. I use fgetc() and I'm not sure it updates the last read location in the FILE pointer or not.

I followed the general idea suggested here, this does not work yet but gets close. The condition check at the beginning does not seem to work well (EOF). Also seems like I am getting an extra character when copying the airline name and after that it will crash.

// Read data from file, data is comma delimited!
flight* read_from_text()
{
    #define DATA_CHUNK 20
    FILE *fp;
    flight temp_data;
    flight *data=malloc(sizeof(*data));
    data=&temp_data;
    char buffer[DATA_CHUNK];
    int c=0,n=0,i=0,state=0;

    // Open file for reading
    if((fp=fopen("c:\\data.txt","r"))==NULL)
    {
        printf("Error opening flight data file.");
        return NULL;
    }

    // read a single entry from file

    while(1)
    {
        while(((c=fgetc(fp))!=',')||(c=!EOF))
            buffer[n++]=(char)c;
        if(c==EOF) break;

        switch(state)
        {
            case CODE:
                // Check if flight code is valid
                if((buffer[0]<'0')||(buffer[0]>'9')||(buffer[1]<'0')||(buffer[1]>'9'))
                    printf("Error reading in flight number\n");
                else
                    temp_data.code=atoi(buffer);
                state++;
                break;
            case AIRLINE_NAME:
                // Check airline name length is OK
                if(n>(sizeof(temp_data.airline_name)))
                    printf("Airline name is too long, some characters will be cut\n");
                strncpy(temp_data.airline_name,buffer,n);
                state++;
                break;
            case DESTINATION:
                if(n>(sizeof(temp_data.destination)))
                    printf("Destination name is too long, some characters will be cut\n");
                strncpy(temp_data.destination,buffer,n);
                state++;
                break;
            case RESERVED_SEATS:
                temp_data.reserved_seats=atoi(buffer);
                state++;
                break;
            case DATE:
                if(n>(sizeof(temp_data.date)))
                    printf("Date format is too long, might be corrupted\n");
                strncpy(temp_data.date,buffer,n);
                state=0;
                break;
        }

        // Clear buffer
        for(i=0;i<DATA_CHUNK;i++)
            buffer[i]='\n';
        n=0;
    }

    printf("%d\n",temp_data.code);
    printf("%s\n",temp_data.airline_name);
    printf("%s\n",temp_data.destination);
    printf("%d\n",temp_data.reserved_seats);
    printf("%s\n",temp_data.date);
    getchar();

    return data;
}
2
You could read it in dynamically line by line and then tokenize it on the commas.ciphermagi
Of course fgetc updates thes last read location in the FILE pointer. If yozu have a file containing "ABC" the first fgetc will return 'A', the second 'B' and so on.Jabberwocky

2 Answers

0
votes

You might also consider reading in lines at a time and using something like strtok to read each substring using ',' as the delimiter. For a simple program this should be ok. strtok has internal state so you can't interleave it with other calls so it is not thread safe. Alternatively, you could check out the function "index" which is in strings.h. It returns a pointer to the first occurance of a character like ','.

In any case, you could just build a simple state machine using fgetc and to answer your question, each subsequent call will get the next character in the file.

0
votes

Yes, function fgetc updates the Read pointer until it returns EOF, indicating the end of the file.

It's because of this EOF that function fgetc returns an int rather than a char.

So when storing the return-value of function fgetc, use an int and not a char.

If it's EOF, then you know that you've reached the end of the file.

Otherwise, cast it to char and proceed "according to plan".

For example:

FILE* fp = fopen(fileName,"r");
int i;
char c;
while (1)
{
    i = fgetc(fp);
    if (i == EOF)
        break;
    c = (char)i;
    ...
}
fclose(fp);