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.