user9414
user9414

Reputation: 39

Reading a file in a table format and print it

So, what I'm trying to do is, at first create a file in a table format then read that file and put that file in 4 different dynamic arrays using struct and print them in order

So, here is the struct I'm using: I used capacity = 5 to change the size of dynamic array later but still don't know how to change it

struct score{
    char *str1;
    char *str2;
    int *num1;
    int *num2;
};

int main(){
    int capacity = 5;
    struct score table;
    table.str1=(char *)malloc(sizeof(int)*capacity);
    table.str2=(char *)malloc(sizeof(int)*capacity);
    table.num1=(int *)malloc(sizeof(int)*capacity);
    table.num2=(int *)malloc(sizeof(int)*capacity);

After I created a File to write:

    inFile = fopen("Subject.txt", "w");
    if(inFile == NULL)
    {
      printf("Error!");   
      exit(1);             
    }

    char names[] = {"Joe Math 52 85\nBilly Phy 65 70\nSophia Chem 86 71"};

    fprintf(inFile,"%s",names);
    fclose(inFile);

At the end reading a File and putting them in arrays:

    inFile = fopen("Subject.txt", "r");
    if(inFile == NULL)
    {
      printf("Error!");   
      exit(1);             
    }
    fscanf(inFile, "%s %s %d %d",table.str1, table.str2, table.num1, table.num2);
    fclose(inFile);

    for(i=0;i<6;i++){
        printf("%s %s %d %d\n",table.str1, table.str2, table.num1, table.num2);
    }

So, I need this code to print like this, and I couldn't do it:

Name   Subj.  Test1  Test2
------------------------
Joe    Math   52     85
Billy  Phy    65     70
Sophia Chem   86     71

Here is my full Code just in case:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct score{
    char *str1;
    char *str2;
    int *num1;
    int *num2;
};

int main(){
    FILE *inFile;
    int num, capacity = 5, i;
    struct score table;
    table.str1=(char *)malloc(sizeof(int)*capacity);
    table.str2=(char *)malloc(sizeof(int)*capacity);
    table.num1=(int *)malloc(sizeof(int)*capacity);
    table.num2=(int *)malloc(sizeof(int)*capacity);
    inFile = fopen("Subject.txt", "w");
    if(inFile == NULL)
    {
      printf("Error!");   
      exit(1);             
    }

    char names[] = {"Joe Math 52 85\nBilly Phy 65 70\nSophia Chem 86 71"};

    fprintf(inFile,"%s",names);
    fclose(inFile);

    inFile = fopen("Subject.txt", "r");
    if(inFile == NULL)
    {
      printf("Error!");   
      exit(1);             
    }
    fscanf(inFile, "%s %s %d %d",table.str1, table.str2, table.num1, table.num2);
    fclose(inFile);

    for(i=0;i<6;i++){
        printf("%s %s %d %d\n",table.str1, table.str2, table.num1, table.num2);
    }
}

Upvotes: 0

Views: 311

Answers (2)

Craig Estey
Craig Estey

Reputation: 33601

You want an array of structs.

But, you've got a fixed number of scores (e.g. num1, num2). This, also, should be an array.

I think you'll be better off with a second struct. That is, struct student and struct score

And, Paul outlined how to do this with fixed limits.

In general, you could allocate things dynamically to accomodate an arbitrary number of students that have an arbitrary (and varying) number of test scores.

Based on your sample data, your input format is:

<name> <subject> <score1> <score2> ... <scoreN>

Because of this, I interpret the subject to be the students major, so it gets grouped in the student record.

Otherwise, we'd need something like:

<name> <subject1> <score1> <subject2> <score2> ... <subjectN> <scoreN>

And, then, the subject would go into the score record


To get it to work, I had to [heavily] refactor your code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct score {
    int score;
};

struct student {
    char *name;
    char *subject;
    struct score *scores;
    int count;
};

int
main(void)
{
    FILE *inFile;
    struct student *students = NULL;
    int student_count = 0;
    struct student *who;
    struct score *score;
    const char *delim = " \t\n";
    char *cp;
    char buf[1000];

    inFile = fopen("Subject.txt", "w");
    if (inFile == NULL) {
        printf("Error!");
        exit(1);
    }

    char names[] = { "Joe Math 52 85\nBilly Phy 65 70\nSophia Chem 86 71" };

    fprintf(inFile, "%s", names);
    fclose(inFile);

    inFile = fopen("Subject.txt", "r");
    if (inFile == NULL) {
        printf("Error!");
        exit(1);
    }

    while (1) {
        // get a line
        cp = fgets(buf,sizeof(buf),inFile);
        if (cp == NULL)
            break;

        // get the student name
        cp = strtok(buf,delim);
        if (cp == NULL)
            continue;

        // allocate new student record
        students = realloc(students,
            sizeof(struct student) * (student_count + 1));
        who = &students[student_count];
        student_count += 1;

        // save the student name
        who->name = strdup(cp);

        // get the subject and save it
        cp = strtok(NULL,delim);
        if (cp == NULL)
            break;
        who->subject = strdup(cp);

        // clear out the scores array
        who->count = 0;
        who->scores = NULL;

        // get all scores
        while (1) {
            cp = strtok(NULL,delim);
            if (cp == NULL)
                break;

            // increase the size of the scores array for this student
            who->scores = realloc(who->scores,
                sizeof(struct score) * (who->count + 1));
            score = &who->scores[who->count];
            who->count += 1;

            score->score = atoi(cp);
        }
    }

    fclose(inFile);

    for (who = &students[0];  who < &students[student_count];  ++who) {
        printf("%10s %10s", who->name, who->subject);

        for (score = who->scores;  score < &who->scores[who->count];  ++score)
            printf("%4d",score->score);

        printf("\n");
    }

    return 0;
}

Here's the program output:

       Joe       Math  52  85
     Billy        Phy  65  70
    Sophia       Chem  86  71

Upvotes: 1

Paul Ogilvie
Paul Ogilvie

Reputation: 25286

I think you want an array of structs with one array element for each student. Now you are using one struct to hold arrays of the individual pieces of information.

The array would look like:

#define MAX_NAME 30
#define MAX_STUDENTS 10

struct score{
    char str1[MAX_NAME];
    char str2[MAX_NAME];
    int num1;
    int num2;
};

struct score table[MAX_STUDENTS];

With this definition you don't need to malloc memory (it is simpler, but not flexible).

You read the information into the array as:

int i=0;
while (fscanf(inFile, "%30s %30s %d %d",table[i].str1, table[i].str2,
  &table[i].num1, &table[i].num2) == 4) {
    i++;
}

Upvotes: 1

Related Questions