1

I have a struct in which I'd like to pass its fields to particular functions. For example, one of the fields in my struct is students quiz grades for quiz1, 'quiz1'. I'd like to calculate the average, max, and min of all the quizes.I'd like to create a function for each computation, but I dont know how to pass a particular field of the struct to a given function. here is what I have:

The struct:

 struct studentData {
        char name[30];
        int quiz1; int quiz2;
        int quiz3; int quiz4;
        int mid1; int mid2;
        int finalexam;
    } ;

the average function:

double calcFAverage(struct studentData *record, int reccount)
{
    float  sum_F,F_avg;
    int k;
            // calculate the score sums
            for (k=0; k<reccount; k++)
            {
                sum_F += record[k].finalexam;
            }
            F_avg = sum_F/reccount;

    return F_avg;   
}

in the main:

struct studentData record[100];
calcFAverage(record,reccount);

The reccount variable holds the number of records for the struct. But, as you can see the average function is specific only to the final exam scores. How can I make it so that I can pass any of the fields in the struct and get its average. Right now I have an average function for each field which is really a bad way of doing it I think.

2
  • With pure C, you need pass an offset, so that the score can be retrieved by *((int*)((char*)&record[k]+offset)). If you use C++, you can pass a pointer to class member like &studentData::mid1 Commented Oct 4, 2015 at 2:28
  • 1
    @YakumoRan: there's a technical term for that suggestion: Yuck! Commented Oct 4, 2015 at 2:31

2 Answers 2

2

Your data structure is not designed to support the calculation you seek to do. You need to redesign your structure. If you want to add the scores of the Quiz 1 results, or the Final Exam results, then you need something more like:

enum { QUIZ1, QUIZ2, QUIZ3, QUIZ4, MID1, MID2, FINAL };

struct studentData
{
    char name[30];
    int marks[7];    
};

and now you can use:

double calcFAverage(struct studentData *record, int n_recs, int markid)
{
    double sum_F = 0.0
    // calculate the score sums
    for (int k = 0; k < n_recs; k++)
        sum_F += record[k].marks[markid];

    double F_avg = sum_F / n_recs;

    return F_avg;   
}

And call it with:

double ave = calculateFAverage(students, n_students, FINAL);
Sign up to request clarification or add additional context in comments.

1 Comment

Excellent answer. Clean, readable, maintainable, extensible - no hanky panky.
0

Like Yakumo's comment, use data alignment. The other possibly better option is to put the scores in an array like the other answer. For instance:

int quiz1offset = (int)(&(record[0].quiz1)) - (int)(record);//This is the location of quiz1 relative to the location of its struct

average(records,reccount,quiz1offset);


double average(struct studentData *record, int reccount, int offset)
{
double  sum,avg;
int k;
        // calculate the score sums
        for (k=0; k<reccount; k++)
        {
            sum += *(int *)((int)(record+k) + offset);
            //equivalent form is sum += *(int *)((int)&record[k] + offset);
        }
        avg = sum/reccount;

return avg;   
}

1 Comment

That's an awkward overwrought approach. In simple cases like this, approaches like that are usually an indication that it is not well designed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.