0
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

The above is the text from the text file.

Here is my code:

#define COUNTRIES 15
#define MEDALCAT 3
#define MAX_LENGTH_CNAME 100

void
readFromFile(char fileWithMedals[30], int country[COUNTRIES][MEDALCAT],
    char countryNames[COUNTRIES][MAX_LENGTH_CNAME])
{

    FILE *cWealth = fopen("commonWealth.txt", "r");
    char single = fgetc(cWealth);

    if (cWealth == NULL) {
        printf("Error! File was not created!");
        exit(1);
    }
    int line = 0;

    while (!feof(cWealth) && !ferror(cWealth)) {
        if (fgets(countryNames[line], MAX_LENGTH_CNAME, cWealth) != NULL) {
            line++;
        }
    }

    fclose(cWealth);

    for (int i = 0; i < line; i++) {
        printf("%s", countryNames[i]);
    }

    fclose(cWealth);
}

I need to somehow read and store only the country names from this. And store the column 1, 2, 3 of numbers seperately.

Craig Estey
  • 30,627
  • 4
  • 24
  • 48
Yuvan
  • 1
  • Please fix the formatting of your question so it's easier to read. – Shawn Nov 22 '22 at 01:37
  • 1
    [`while(!feof(fp))` is always wrong](https://stackoverflow.com/questions/5431941). The loop should be `while (fgets(...) != NULL)`. Inside the loop, use `sscanf` to extract and copy the name into the structure. – user3386109 Nov 22 '22 at 01:50

1 Answers1

1

A few issues ...

  1. char single = fgetc(cWealth); should be done after the if (cWealth == NULL) block.
  2. It serves no purpose and would be flagged by the compiler with -Wall
  3. As mentioned above use of feof [and ferror] are wrong.
  4. You have "parallel" arrays (country and countryNames), indexed by the country count/index. Better to use a struct.
  5. fileWithMedals is not used. Why is it length 30 (a hardwired/magic constant)?
  6. I'm guessing this is the filename to open??? But, you open "commonWealth.txt"?
  7. 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:

  1. The first method is the simplest translation of the code. But, it assumes hardwired values for MAX_LENGTH_CNAME and MEDALCAT
  2. 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
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • We have to only use 'commonWealth.txt'. There was no other txt file attached to the assignment. Thx for the other inputs – Yuvan Nov 22 '22 at 03:10