Home > Blockchain >  I want to read a file and save them into the array of struct how can I do it?
I want to read a file and save them into the array of struct how can I do it?

Time:12-01

I'm very new to file and struct and I just don't know how to do it. Now, I try to find how to do it everywhere but I can't find it. This is my code.

#include <stdio.h>

typedef struct
{
    int site_id_num;
    int day_of_month[14];
    int wind_speed[14];
    int temperature[14];
}measured_data_t;

int main()
{
    FILE *read;

    measured_data_t station[5];

    read = fopen("data", "r");

    for(int i = 0; i < 5; i  )
    {
        for(int j = 0; j < 14; j  )
        {
            fscanf(read, "%d %d %d %d", station[i].site_id_num, station[i].day_of_month[j], station[i].wind_speed[j], station[i].temperature[j]);
        }
    }

    for(int i = 0; i < 5; i  )
    {
        for(int j = 0; j < 14; j  )
        {
            printf("%d %d %d %d\n", station[i].site_id_num, station[i].day_of_month[j], station[i].wind_speed[j], station[i].temperature[j]);
        }
    }


    fclose(read);

    return 1;   
}

And this is the text file that I want to read and save into an array of struct.

1000 1 6 22
1000 2 9 21
1000 3 15 27
1000 4 24 26
1000 5 11 23
1000 6 24 22
1000 7 21 16
1000 8 10 20
1000 9 22 22
1000 10 3 25
1000 11 14 32
1000 12 23 33
1000 13 4 22
1000 14 25 35
2000 1 13 20
2000 2 1 28
2000 3 18 31
2000 4 2 34
2000 5 4 31
2000 6 18 15
2000 7 10 34
2000 8 14 33
2000 9 12 25
2000 10 11 24
2000 11 6 21
2000 12 12 26
2000 13 17 35
2000 14 20 25
3000 1 5 23
3000 2 17 33
3000 3 20 19
3000 4 7 35
3000 5 17 16
3000 6 2 28
3000 7 13 15
3000 8 23 33
3000 9 19 19
3000 10 16 27
3000 11 21 28
3000 12 22 18
3000 13 11 20
3000 14 1 32
4000 1 10 30
4000 2 2 28
4000 3 24 19
4000 4 11 22
4000 5 25 26
4000 6 1 23
4000 7 24 16
4000 8 13 24
4000 9 23 28
4000 10 2 15
4000 11 3 24
4000 12 7 28
4000 13 17 16
4000 14 10 18
5000 1 12 31
5000 2 10 24
5000 3 3 18
5000 4 25 16
5000 5 14 21
5000 6 11 24
5000 7 15 29
5000 8 4 28
5000 9 2 28
5000 10 22 21
5000 11 9 18
500 12 11 16
5000 13 2 33
5000 14 21 27

I want each station to have id, 14 days, 14 wind speeds, and 14 temperatures. But I have no clues right now. Please help me.

CodePudding user response:

If your data is indeed fixed format like this then you just need to pass in the address of your variables when calling fscanf(). Initialized the array so at least you will 0 values if the data doesn't conform. Check the return value from fscanf() to ensure you read 4 numbers. Use sizeof() instead of hard-coding the array sizes. Don't return 1 which means there was an error.

#include <stdio.h>

typedef struct {
    int site_id_num;
    int day_of_month[14];
    int wind_speed[14];
    int temperature[14];
} measured_data_t;

int main(void) {
    FILE *read = fopen("data", "r");
    measured_data_t station[5] = { 0 };
    for(size_t i = 0; i < sizeof station / sizeof *station; i  ) {
        for(size_t j = 0; j < sizeof station->day_of_month / sizeof *station->day_of_month; j  ) {
            int r = fscanf(read, "%d %d %d %d",
                &station[i].site_id_num,
                &station[i].day_of_month[j],
                &station[i].wind_speed[j],
                &station[i].temperature[j]
            );
            if(r != 4) {
                printf("fscanf failed\n");
                return 1;
            }
        }
    }
    fclose(read);

    for(size_t i = 0; i < sizeof station / sizeof *station; i  )
        for(size_t j = 0; j < sizeof station->day_of_month / sizeof *station->day_of_month; j  )
            printf("%d %d %d %d\n", station[i].site_id_num, station[i].day_of_month[j], station[i].wind_speed[j], station[i].temperature[j]);
}

CodePudding user response:

Obvious fix of an error that a decent compiler should warn about:

main.c: In function ‘main’:
main.c:23:28: warning: format ‘%d’ expects argument of type ‘int *’, but argument 3 has type ‘int’ [-Wformat=]
   23 |             fscanf(read, "%d %d %d %d", station[i].site_id_num, station[i].day_of_month[j], station[i].wind_speed[j], station[i].temperature[j]);
      |                           ~^            ~~~~~~~~~~~~~~~~~~~~~~
      |                            |                      |
      |                            int *                  int
main.c:23:31: warning: format ‘%d’ expects argument of type ‘int *’, but argument 4 has type ‘int’ [-Wformat=]

etc.

Use the address operator & to pass the address of the variable where fscanf shall store the value:

            fscanf(read, "%d %d %d %d", &station[i].site_id_num, &station[i].day_of_month[j], &station[i].wind_speed[j], &station[i].temperature[j]);

There are more problems in the code:

You should check the return value of all *scanf functions. It is the number of converted items which is expected to be 4 in your case.

Better read a line of input using fscanf and parse the string using sscanf. This avoids getting out of sync in case an input line contains an error or more or less values than expected.

            char line[100];
            if(fgets(line, sizeof(line), read) == NULL)
            {
                /* handle EOF or error */
            }
            /* check for trailing newline to detect input lines that are too long */
            if(sscanf(line, "%d %d %d %d", &station[i].site_id_num, &station[i].day_of_month[j], &station[i].wind_speed[j], &station[i].temperature[j]) != 4)
            {
                /* handle error */
            }

Your code is implemented in a way that the loops must match (predict) the input, i.e. 5 stations with 14 records each. I suggest to read the data into a temporary structure or temporary variables, compare the station ID to check if you have the next record for the same station or the next station, and copy the data into the final location.

Instead of using 3 arrays in the structure which in fact represent a set of data records, I suggest to use an array of structures.

typedef struct
{
    int site_id_num;
    struct record {
        int day_of_month;
        int wind_speed;
        int temperature;
    } data[14];
}measured_data_t;
  • Related