A few issues ...
char single = fgetc(cWealth);
should be done after the if (cWealth == NULL)
block.
- It serves no purpose and would be flagged by the compiler with
-Wall
- As mentioned above use of
feof
[and ferror
] are wrong.
- You have "parallel" arrays (
country
and countryNames
), indexed by the country count/index. Better to use a struct
.
fileWithMedals
is not used. Why is it length 30
(a hardwired/magic constant)?
- I'm guessing this is the filename to open??? But, you open
"commonWealth.txt"
?
fclose
is called twice. The second call will bork.
Here is the refactored code. It uses a struct
to combine the data. It shows two ways to read the input:
- The first method is the simplest translation of the code. But, it assumes hardwired values for
MAX_LENGTH_CNAME
and MEDALCAT
- The second method allows those
#define
to be changed arbitrarily.
#include <stdio.h>
#include <stdlib.h>
#define COUNTRIES 15 // max number of countries
#define MEDALCAT 3 // max number of medals / country
#define MAX_LENGTH_CNAME 100 // maximum country name length
struct country {
char name[MAX_LENGTH_CNAME]; // country name
int medals[MEDALCAT]; // medals won
};
int
readFromFile(const char *fileWithMedals,struct country countries[COUNTRIES])
{
FILE *cWealth = fopen(fileWithMedals, "r");
if (cWealth == NULL) {
printf("Error! File was not created!");
exit(1);
}
int count = 0;
char buffer[1000];
struct country *country;
int *medals;
while (fgets(buffer,sizeof(buffer),cWealth) != NULL) {
// too many countries? should we error out here?
if (count >= COUNTRIES)
break;
country = &countries[count];
medals = country->medals;
// syntax error -- should we error out here?
if (sscanf(buffer,"%99s %d %d %d",
country->name,&medals[0],&medals[1],&medals[2]) != 4)
continue;
++count;
}
fclose(cWealth);
for (int i = 0; i < count; i++) {
country = &countries[i];
medals = country->medals;
printf("%s %d %d %d\n",
country->name,medals[0],medals[1],medals[2]);
}
return count;
}
int
readFromFile2(const char *fileWithMedals,struct country countries[COUNTRIES])
{
FILE *cWealth = fopen(fileWithMedals, "r");
if (cWealth == NULL) {
printf("Error! File was not created!");
exit(1);
}
int count = 0;
struct country *country;
int *medals;
// given that MAX_LENGTH_CNAME is 100, we want a format of "%99s" for
// safety with fscanf
char namefmt[10];
sprintf(namefmt,"%%%ds",MAX_LENGTH_CNAME - 1);
while (1) {
// too many countries? should we error out here?
if (count >= COUNTRIES)
break;
country = &countries[count];
medals = country->medals;
if (fscanf(cWealth,namefmt,country->name) != 1)
exit(1);
for (int i = 0; i < MEDALCAT; ++i) {
if (fscanf(cWealth,"%d",&medals[i]) != 1)
exit(2);
}
++count;
}
fclose(cWealth);
for (int i = 0; i < count; i++) {
country = &countries[i];
medals = country->medals;
printf("%s",country->name);
for (int j = 0; j < MEDALCAT; ++j)
printf(" %d",medals[j]);
printf("\n");
}
return count;
}
int
main(int argc,char **argv)
{
--argc;
++argv;
if (argc != 1) {
fprintf(stderr,"need filename\n");
exit(1);
}
struct country countries[COUNTRIES];
printf("ORIGINAL:\n");
readFromFile(argv[0],countries);
printf("\nMODIFIED:\n");
readFromFile2(argv[0],countries);
return 0;
}
For the given input file, here is the program output:
ORIGINAL:
Australia 67 57 54
England 57 66 53
Canada 26 32 34
India 22 16 23
NewZealand 20 12 17
Scotland 13 11 27
Nigeria 12 9 14
Wales 8 6 14
SAfrica 7 9 11
Uganda 3 0 2
Samoa 1 4 0
BVIslands 2 0 0
Ghana 0 2 3
Namibia 0 0 4
Dominica 0 2 0
MODIFIED:
Australia 67 57 54
England 57 66 53
Canada 26 32 34
India 22 16 23
NewZealand 20 12 17
Scotland 13 11 27
Nigeria 12 9 14
Wales 8 6 14
SAfrica 7 9 11
Uganda 3 0 2
Samoa 1 4 0
BVIslands 2 0 0
Ghana 0 2 3
Namibia 0 0 4
Dominica 0 2 0