Thread: Array Question

  1. #46
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Quote Originally Posted by Sorinx View Post
    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]);
    Fact - Beethoven wrote his first symphony in C

  2. #47
    Registered User
    Join Date
    Oct 2012
    Posts
    126
    I'll have to look into this more on the weekend have another problem I have to finish sadly

  3. #48
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    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.

  4. #49
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Once again, the voice of reason: Nominal animal. Can you give a feash prospect to this conundrum?

  5. #50
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    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:
    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].
    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[]);
    (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.

    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);
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 12
    Last Post: 11-21-2010, 09:46 AM
  2. Array question HELP!!
    By evangela in forum C Programming
    Replies: 7
    Last Post: 11-28-2009, 12:38 PM
  3. Array question
    By Karmachrome in forum C Programming
    Replies: 4
    Last Post: 10-27-2005, 09:33 PM
  4. array question
    By KAchE in forum C Programming
    Replies: 4
    Last Post: 02-18-2002, 06:33 PM
  5. Array Question
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 11-03-2001, 05:23 PM