Home > Mobile >  Printing file info in an array of structs, giving random output
Printing file info in an array of structs, giving random output

Time:12-02

I'm reading some file info into an array of structs but, when I print out the array of structs, I run into a weird output that I can't seem to understand.

Could someone explain what I've done wrong and why the output is the way it is?

My code:

#include <stdio.h>

typedef struct kamp{
    char ugedag[4];
    char dato[6];
    double klokkeslaet;
    char hold[10];
    char resultat[6];
    int tilskuer;
} kamp;

int main(void){
    FILE *kampe_2022_2023;
    kampe_2022_2023 = fopen("kampe-2022-2023.txt", "r");

    if (kampe_2022_2023 == NULL)
    {
        printf("Error reading file");
        return 1;
    }
    
    kamp superliga_resultat[5];
    
    for (int i = 0; i < 5; i  )
    {
        fscanf(kampe_2022_2023, "%s %s %lf %s %s %d", superliga_resultat[i].ugedag,
                                                      superliga_resultat[i].dato,
                                                      &superliga_resultat[i].klokkeslaet,
                                                      superliga_resultat[i].hold,
                                                      superliga_resultat[i].resultat,
                                                      &superliga_resultat[i].tilskuer);
    }
    
    for (int i = 0; i < 5; i  )
    {
        printf("%s     %s %.2lf     %s     %s      %d\n", superliga_resultat[i].ugedag,
                                                          superliga_resultat[i].dato,
                                                          superliga_resultat[i].klokkeslaet,
                                                          superliga_resultat[i].hold,
                                                          superliga_resultat[i].resultat,
                                                          superliga_resultat[i].tilskuer);
    }
    

    fclose(kampe_2022_2023);

    return(0);
}

The File:

Fre     15/07 19.00     FCM - RFC     1 - 1      7359
Son     17/07 14.00     VFF - AaB     2 - 1      4681
Son     17/07 14.00     LBK - SIF     2 - 2      3871
Son     17/07 16.00     FCK - ACH     0 - 1     22184
Son     17/07 18.00     BIF - AGF     1 - 0     17022

The Output:

Fre     15/07 19.00     FCM     -      1
RFC     1 0.00                6417484
1     7359 0.00          ¼wÉýa      6418744
Son     17/07 14.00     VFF     -      512
AaB     2 30231459790598215000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00     ╝îlv\L¡w±îlv³     lv³      1

CodePudding user response:

The string fields you want for hold and resutat have spaces in them in the input file, so they cannot be read using a simple %s format specifier (which stops input on the first whitespace after it has found a non-space character). Thus, after reading the first line, hold will have only the "FCM" string and resultat will be "-" … and the remaining characters of the first line will not match the subsequent %d format specifier, causing a failure. That error will then persist throughout the file-read loop.

So, first and foremost (as mentioned in the comments), you should always check the return value of functions like fscanf, to make sure the correct number of items were read (and handle cases where they weren't).

Then, to resolve the issue of spaces in your string data, you can use the "set" format specifier (see here) and an "exclude" character (one that won't ever be in the actual data) preceded by a ^. Further, as you appear to have fixed-length data for the hold and resultat data, you can specify that length so that reading stops after n characters. The space before the two set formats will ensure that all whitespace preceding the fields will be skipped.

Here's the code modified to use those "set" format specifiers:

int main(void)
{
    FILE* kampe_2022_2023;
    kampe_2022_2023 = fopen("kampe-2022-2023.txt", "r");
    if (kampe_2022_2023 == NULL)
    {
        printf("Error opening file");
        return 1;
    }
    kamp superliga_resultat[5];
    for (int i = 0; i < 5; i  )
    {
        int items = fscanf(kampe_2022_2023, "%3s %5s %lf %9[^#] %5[^#] %d", // Can change "#" as required
            superliga_resultat[i].ugedag,
            superliga_resultat[i].dato,
            &superliga_resultat[i].klokkeslaet,
            superliga_resultat[i].hold,
            superliga_resultat[i].resultat,
            &superliga_resultat[i].tilskuer);
        if (items != 6) {
            printf("Error reading file...");
            fclose(kampe_2022_2023);
            return 1;
        }
    }
    for (int i = 0; i < 5; i  )
    {
        printf("%s     %s %.2lf     %s     %s      %d\n", 
            superliga_resultat[i].ugedag,
            superliga_resultat[i].dato,
            superliga_resultat[i].klokkeslaet,
            superliga_resultat[i].hold,
            superliga_resultat[i].resultat,
            superliga_resultat[i].tilskuer);
    }
    fclose(kampe_2022_2023);
    return(0);
}

You might like to use \n (the newline) in place of the # as the 'exclude character', because that is very unlikely to ever be in the actual field.

Also, note that I have added (maximum) length fields to the first two %s specifiers. You should make this a habit because, as mentioned on the linked website, not doing so is dangerous.

  • Related