Home > database >  Multiple fscanf statements in a loop. How do I get when EOF is reached?
Multiple fscanf statements in a loop. How do I get when EOF is reached?

Time:06-23

I'm having problems while reading a file -again. Here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct camion {
    int data[3];
    int numeropacchi;
    char *hubprovenienza[100];
    _Bool iseccezionale;
};

int main(void) {
    struct camion **listacamion = malloc(sizeof(struct camion * ));
    listacamion[0] = calloc(1, sizeof(struct camion));
    int numerocamion = 0;
    //importazione
    FILE *input = fopen("info.txt", "r");

    if (input != NULL) {
        char *temp = calloc(100, sizeof(char));

        for (int i = 0; true; i  ) {
            //1, 2, 3
            fscanf(input, "%d - %d - %d",
                   &listacamion[i]->data[0],
                   &listacamion[i]->data[1],
                   &listacamion[i]->data[2]);
            printf("ORA %d-%d-%d\n",
                   listacamion[i]->data[0],
                   listacamion[i]->data[1],
                   listacamion[i]->data[2]);
            fscanf(input, "%d", &listacamion[i]->numeropacchi);
            printf("NUMERO PACCHI %d\n", listacamion[i]->numeropacchi);
            if (fscanf(input, "%s", listacamion[i]->hubprovenienza) == EOF) {
                listacamion[i]->iseccezionale = false;
                break;
            }
            printf("HUB PROVENIENZA %s\n", listacamion[i]->hubprovenienza);

            //4
            char eccezionale;
            long i_senoneccezionale = ftell(input);
            if (fscanf(input, "%s", temp) == EOF)
                break;
            else { //if not EOF alloc mem for the next truck
                listacamion = realloc(listacamion, sizeof(struct camion *) * (i   1));
                listacamion[i   1] = calloc(1, sizeof(struct camion))
                numerocamion  ;
                printf("RIALLOCATA!\n");
            }
            if (temp[0] == 'E') //if 'E' is there, bool is true 
                listacamion[i]->iseccezionale = true;
            else {
                //otherwise go back to the saved pointer
                listacamion[i]->iseccezionale = false;
                fseek(input, i_senoneccezionale, SEEK_SET);
            }
            //set temp to zero;
            free(temp);
            temp = calloc(100, sizeof(char));
            //---
            printf("YES OR NO %d\n\n", listacamion[i]->iseccezionale);
        }
    }
    //---

    return 0;
}

Here's the input file I use:

22 - 03 - 2020
39
Bergamo
E
30 - 05 - 2021
90
Napoli
19 - 02 - 2022
132
Bari
21 - 03 - 2022
1721
Modena
E

I've got 3 or 4 lines per camion (truck) in my file, depending on whether the load is oversized or not (if it is, then an 'E' is put, otherwise the line in the file doesn't exist). So the end of the file could be detected either at the third fscanf or the fourth, but I'm not sure fscanf works this way... The issue is that the loop is correctly executed 3 times out of 4 (I've got the info of 4 trucks), then I get a segmentation fault, so I assumed that the problem might be an inadequate detection of the end of the file. I've tried other options - feof for example - but they weren't useful, and I can only find examples of a fscanf used as a condition, while my condition is just a true because I have different fscanfs...

Here's my output:

ORA 22-3-2020
NUMERO PACCHI 39
HUB PROVENIENZA Bergamo
RIALLOCATA!
YES OR NO 1

ORA 30-5-2021
NUMERO PACCHI 90
HUB PROVENIENZA Napoli
RIALLOCATA!
YES OR NO 0

ORA 19-2-2022
NUMERO PACCHI 132
HUB PROVENIENZA Bari
RIALLOCATA!

--------------------------------
Process exited after 0.4117 seconds with return value 3221226356

CodePudding user response:

You should test the return value of every call to fscanf(): fscanf returns the number of successful conversions. A return value different from the number of conversions requested is an indication of invalid or missing input. Both must be handled to avoid undefined behavior.

fscanf(input, "%s", temp) is risky: a word longer than 99 bytes will cause a buffer overflow. You should write fscanf(input, "

  • Related