Post #34

Quote:

Originally Posted bySorinx

Post #35

Quote:

Originally Posted byClick_here

Post #17

Quote:

Originally Posted byClick_here

Printable View

- 11-15-2012Click_here
- 11-15-2012Sorinx
I'll have to look into this more on the weekend have another problem I have to finish sadly

- 11-16-2012Nominal Animal
Perhaps it might help to look at it a different way.

Assume you have STUDENTS students, COURSES courses, and PARTS parts to each course, with each part graded:

Code:`#define STUDENTS 20`

#define COURSES 5

#define PARTS 3

For example, if you define

Code:`double grade[STUDENTS][COURSES][PARTS];`

*student*] is a two-dimensional array, double[COURSES][PARTS], specifying the grades for one student over all courses and parts, and grade[*student*][*course*] is an one-dimensional array, double[PARTS], specifying the grades for each part for one student on one course.

If, however, you define

Code:`double grade[COURSES][PARTS][STUDENTS];`

*course*] is a two-dimensional array, double[PARTS][STUDENTS], specifying the grades for all students and all parts of that course, and grade[*course*][*part*] is an one-dimensional array, double[STUDENTS], specifying the grades for a specific course and part for all students.

So, the way you define your array indices, define the ways you can use your arrays in C.

For general-purpose one-, two-, or three-dimensional arrays, I would use

Code:`struct data {`

struct data *next;

long refcount;

size_t size;

double data[];

};

struct array3d {

long step[3];

long size[3];

double *origin;

struct data *owner;

};

struct array2d {

long step[2];

long size[2];

double *origin;

struct data *owner;

};

struct array1d {

long step;

long size;

double *origin;

struct data *owner;

};

#define ELEMENT3D(array, x, y, z) \

((array)->origin[(x)*(array)->step[0] + (y)*(array)->step[1] + (z)*(array)->step[2]])

#define ELEMENT2D(array, x, y) \

((array)->origin[(x)*(array)->step[0] + (y)*(array)->step[1]])

#define ELEMENT1D(array, x) \

((array)->origin[(x)*(array)->step])

The point of the structures is that actual data is stored in the first structure, and the others just*reference*the data. (Counting the number of references to each instance of the first structure allows the program/library to free the data when it is no longer needed, as long as the programmer remembers to free each array when no longer needed.)

(I use long for the size and step fields, because int is not large enough on 64-bit architectures.)

Given a 3D array, a 2D array can be any regular plane within the array. (Regular in the sense that the coordinates for the elements must be specified with a linear integer equation.)

Given a 3D or 2D array, an 1D array can be any regular line within the array. (Again, regular in the sense that the coordinates for the elements must be specified with an linear integer equation.)

In other words, you can mirror, flip, and/or pick every*N*'th element from another array (having equal or greater number of dimensions).

(It is also possible to expand certain 1D arrays to 2D and 3D, and 2D arrays to 3D, if the same data is repeated. For example, you can create a 3D array with any number of elements, with all the elements always having the exact same value, since they all share the same data.)

There is a very small additional cost to every element access, because all coordinates are multiplied to get the actual address, but it should be neglible in practice. In fact, Fortran does something very, very similar internally, to support arrays and array slicing. - 11-16-2012Click_here
Once again, the voice of reason: Nominal animal. Can you give a feash prospect to this conundrum?

- 11-16-2012Nominal Animal
I'm not sure if asking me is a good idea, Click_here. I seem to have a knack of raising hackles, even if I'm sincirely just trying to help.

Let's start at the beginning, the assignment:

Quote:

Printing an average of all grades

Finding average grade for each subject for each student

Finding the average grade for each student in both subjects

2 subjects, 3 students, 4 exams

Code:`#define STUDENTS 3`

#define SUBJECTS 2

#define EXAMS 4

double grade[STUDENTS][SUBJECTS][EXAMS];

*average*(grade[*student*][*subject*]), where the parameter is of type double[EXAMS].

The grade per student is then*average*(grade[*student*]), where the parameter is of type double[SUBJECTS][EXAMS].

The average grade is*average*(grade).

However, you need to output the intermediate averages too.

So, declare separate arrays for the averages, and an averaging function that takes an one-dimensional array as a parameter:

Code:`double subject_grades[STUDENTS][SUBJECTS];`

double student_grades[STUDENTS];

double average_grade;

double average(const double value[], const size_t values[]);

To populate the subject_grades array, you do a double loop, and calculate the average over the exams in that subject for that student.

Instead of calculating the student grades (student_grades array) from the grades array, you can calculate the averages of averages, i.e. averaging the subject_grades.

Finally, instead of calculating an average over the entire array to get the average grade overall, you average over the student_grades array.

I'll do the unthinkable and show the actual solution, because it really is this trivial:

Code:`int student, subject;`

for (student = 0; student < STUDENTS; student++) {

/* Average grade per subject for this student: */

for (subject = 0; subject < SUBJECTS; subject++)

subject_grades[student][subject] = average(grades[student][subject], EXAMS);

/* Average grade for this student overall: */

student_grades[student] = average(subject_grades[student], SUBJECTS);

}

/* Average grade over all students (and subjects): */

average_grade = average(student_grades, STUDENTS);

Of course, calculating the average grade of all students per subject would be easy to do using two for loops:

Code:`double average_subject[SUBJECTS];`

for (subject = 0; subject < SUBJECTS; subject++) {

average_subject[subject] = 0.0;

for (student = 0; student < STUDENTS; student++)

average_subject[subject] += subject_grades[student][subject];

average_subject[subject] /= (double)STUDENTS;

}

I sincirely hope this clears the question. If not, please be gentle with your rebukes.