-1

I've been struggling with C pointers for hours now. I'm trying to create a C program which manages flights. A flight contains the following:

flight-number, from, to, date, price

OS772,Vienna,New York,15.12.2018,638.00

Therefore, I'm reading a textfile of this given structure. On every line read, I need to create another struct and add it to my array or "list" of structs.

The struct looks like:

typedef struct flights {
    char *flnum;
    char *from;
    char *to;
    char *date;
    float price;
    struct person *fPerson;
}flights;

My problem: Inside the function, the array of structs is created properly. But back in the main-function, the pointer to the array called 'flights **flight_list' is still NULL.

Here is the code (only the necessary parts):

int main(void) {

    flights **flight_list = NULL;
    int numFlights = 0;

    if (!(numFlights = load_flights(flight_list)))      
        return EXIT_FAILURE;

    /* value of flight_list = 0x0000 -> unchanged! */
    /* ... */

Function short load_flights(flights **flight_list):

short load_flights(flights **flight_list) {

    FILE *fp = NULL;
    char file_buffer[256] = {};
    int i = 0;

    if (fp = fopen("flights.txt", "r")) {

        /* create array of structs */
        flight_list = (flights **)calloc(1, sizeof(int));

        while (!feof(fp)) {

            /* read current line of flight from textfile */
            fgets(file_buffer, sizeof(file_buffer), fp);

            /* create a new struct and add it to the array */
            if ((flight_list[i] = (flights *)calloc(1, sizeof(flights))) != NULL) {

                /* create every variable of the struct */
                flight_list[i]->flnum = (char *)calloc(1, strlen(ptr)+1);

                /* ... */

            }

            i++;
        }
    }
    else return 0;

    /* values of the struct-array are properly set; look in attached picture */

    return i;
}

This image was taken while debugging the array-creation process before return i;:

viewing array of struct

And here outside the function; inside main:

viewing array of structs in main

So, why is my array of structs gone in the main-function?

Michael Gierer
  • 401
  • 2
  • 6
  • 15
  • C11 draft standard n1570: *4 An argument may be an expression of any complete object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument. 93) A function may change the values of its parameters, but these changes cannot affect the values of the arguments.* – EOF May 29 '19 at 21:23

1 Answers1

0

You need to pass the address of a pointer variable to load_flights. Then load_flights needs to indirect through the variable to modify the caller's variable.

To handle the dynamic size of the input, you need to use realloc() each time through the loop to grow the array.

int main(void) {

    flights **flight_list = NULL;
    int numFlights = 0;

    if (!(numFlights = load_flights(&flight_list)))      
        return EXIT_FAILURE;

    /* ... */
}

short load_flights(flights ***flight_list) {

    FILE *fp = NULL;
    char file_buffer[256] = {};
    int i = 0;

    if (fp = fopen("flights.txt", "r")) {

        /* create array of structs */
        flight_list **temp_flight_list = NULL;

        /* read current line of flight from textfile */
        while (fgets(file_buffer, sizeof(file_buffer), fp)) {
            // Grow the flight list array
            flights **new_flight_list = realloc(*flight_list, (i+1) * sizeof(flight_list *));
            if (new_flight_list == NULL) { // allocation failed, throw everything away
                for (int j = 0; j < i-1; j++) {
                    free(temp_flight_list[i]->flnum);
                    free(temp_flight_list[i]->from);
                    /* ... */
                    free(temp_flight_list[i]);
                }
                free(temp_flight_list);
                return 0;
            }
            temp_flight_list = new_flight_list;
            /* create a new struct and add it to the array */
            if ((temp_flight_list[i] = calloc(1, sizeof(flights))) != NULL) {
                // Parse the buffer ...
                /* create every variable of the struct */
                temp_flight_list[i]->flnum = calloc(1, strlen(ptr)+1);

                /* ... */

            } else { // allocation failed, throw everything away
                for (int j = 0; j < i-1; j++) {
                    free(temp_flight_list[i]->flnum);
                    free(temp_flight_list[i]->from);
                    /* ... */
                    free(temp_flight_list[i]);
                }
                free(temp_flight_list);
                return 0;
            }
            i++;
        }
        // Store new flight list in caller's variable
        *flight_list = temp_flight_list;
        return i;
    }
    else return 0;

}

See also

Do I cast the result of malloc?

and

Why is “while (!feof(file))” always wrong?

Barmar
  • 741,623
  • 53
  • 500
  • 612