# Array Question

Show 80 post(s) from this thread on one page
Page 4 of 4 First 1234
• 11-15-2012
Click_here
Quote:

Originally Posted by Sorinx
I did try it, it gave me the error I posted previously

Post #34
Quote:

Originally Posted by Sorinx
Code:

```... sAve(&stu); ...```
Lab8a.c:9:6: note: expected 'float (*)[][4]' but argument is of type 'float (*)[
2][3][4]'

Post #35
Quote:

Originally Posted by Click_here
The error comes from the way you are calling sAve -> You are putting a pointer to a 3D array into a pointer to a 2D.

Post #17
Quote:

Originally Posted by Click_here
Code:

```print_s(&arr2D[0]); print_s(&arr2D[1]);```

• 11-15-2012
Sorinx
I'll have to look into this more on the weekend have another problem I have to finish sadly
• 11-16-2012
Nominal 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```
The order of the dimensions determines what you can overall refer to.

For example, if you define
Code:

`double grade[STUDENTS][COURSES][PARTS];`
then grade[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];`
then grade[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 functions to handle this are straightforward, but require detailed knowledge about structures and pointers.

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-2012
Click_here
Once again, the voice of reason: Nominal animal. Can you give a feash prospect to this conundrum?
• 11-16-2012
Nominal 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
First, define the constants and the grade array.
Code:

```#define  STUDENTS  3 #define  SUBJECTS  2 #define  EXAMS    4 double grade[STUDENTS][SUBJECTS][EXAMS];```
The grade per student per subject is then 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].

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[]);```
(I'm sure most of the readers have now realized my point.)

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

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);```
If you wanted the average grade over all students for each subject, you cannot use the same function: you just cannot slice the existing arrays that way. This is the point I was trying to make earlier: the order of indices determines how you can slice the array.

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;     }```
If you look at the indexing, you'll realize that the inner loop accesses nonconsecutive members in the subject_gradesarray. Again, that means you cannot "slice" them to a function, the way we did earlier for the other arrays.

I sincirely hope this clears the question. If not, please be gentle with your rebukes.
Show 80 post(s) from this thread on one page
Page 4 of 4 First 1234