-1

I'm trying to call the getAverage function in the last cout on printResults, but when I call it, it just give me the same average for all the cases. For example, if I put that first students grades are 50 50 and 50, the average would come 50 for the second and third even if they have different scores. I tried a loop with the first and second index, but it sums all of the points of each row. I want it to sum only the points of one row and give me the average. Then when I call it again sum the second row and give me the average. All of this without declaring another variable. (The code is an assigment and I have to do it this way)

#include <iostream>
using namespace std;

const int EXAMS = 3;
void getScores(int[][EXAMS], const int);

int getAverage(int[], const int); // this method requires an array and its length as parameters
char getGrade(int);
void printResults(int[][EXAMS], const int); 

int main() {
    const int STUDENTS = 5;
    int scores[STUDENTS][EXAMS] = {0};
    printResults(scores, STUDENTS);
    cout << endl;
    system("pause"); // for Visual Studio only
    return 0;
}

void getScores(int scores[][EXAMS], const int students)
{

    for (int i = 0; i < students; i++)
    {
        for (int j = 0; j < EXAMS; j++)
        {
            cout << "Enter the score for student #" << i + 1 << ", test #" << j + 1 << ": ";
            cin >> scores[i][j];
        }
        cout << endl;
    }
    
}

// The getAverage method receives an array and its length as parameters, and 
// returns an integer value. It computes the average by adding the values in 
// the array, which are stored in the integer variable sum, and then dividing 
// by the array's size. Use a for iteration control structure to add all the values.
int getAverage(int scores[][EXAMS], const int students)
{
    int sum = 0;
    for (int i = 0; i < EXAMS; i++)
    {
        sum += scores[0][i];
    }

    return sum / EXAMS;
}

// DO NOT DECLARE any variables in this method.
char getGrade(int finalAverage)
{
    if (finalAverage < 59)
        return 'F';
    else if (finalAverage < 69)
        return 'D';
    else if (finalAverage < 79)
        return 'C';
    else if (finalAverage < 89)
        return 'B';
    else
        return 'A';
}

// DO NOT DECLARE any variables in this method.
void printResults(int scores[][EXAMS], const int students)
{
    getScores(scores, students);

    for(int j = 0; j < students; j++)
    {
        cout << "The student with test scores ";
        for (int i = 0; i < EXAMS; i++)
        {
            if (i == EXAMS - 1)
                cout << "and " << scores[j][i] << ", ";
            else
                cout << scores[j][i] << ", ";
        }
        cout << "scored a final average of " << getAverage(scores, students) << " and earned a(n) " << getGrade(getAverage(scores, students)) << endl;
    }
}

I would solve it this way, without the function. But the assignment reequires me to do it with the function and without declaring any variables in the printResults method.

void printResults(int scores[][EXAMS], const int students)
{
    getScores(scores, students);
    

    for(int j = 0; j < students; j++)
    {   
        int sum = 0;
        cout << "The student with test scores ";
        for (int i = 0; i < EXAMS; i++)
        {
            if (i == EXAMS - 1)
                cout << "and " << scores[j][i] << ", ";
            else
                cout << scores[j][i] << ", ";

            sum += scores[j][i];
        }
        cout << "scored a final average of " << sum / EXAMS << " and earned a(n) " << getGrade(sum / EXAMS) << endl;
    }
}
nill9090
  • 3
  • 2
  • 1
    I recommend not to use "C" style arrays anymore (keeping size and content in sync needs to be done manually and is a source of bugs). Have a look at std::vector and use std::vector> for arrays (of arrays) that can change size at runtime. – Pepijn Kramer Oct 02 '22 at 08:11
  • Did you write the line `int getAverage(int scores[][EXAMS], const int students)` yourself or was that line given to you as part of the assignment? I am asking because I am not sure if `int scores[][EXAMS]` is correct. – Andreas Wenzel Oct 02 '22 at 08:56
  • As for the question in the title - One row of a 2d array is a 1d array. Seems like `getAverage` is expecting just that. – BoP Oct 02 '22 at 09:34
  • @AndreasWenzel Yes, I wrote it myself. The instructions says that the function receive an array, but I only have a 2d array, the other functions said that they receive a two dimensional array. How can I fix it? – nill9090 Oct 02 '22 at 19:42

2 Answers2

0

I solved it by putting the j counter as an input on the second parameter of the getAverage function.

int getAverage(int scores[][EXAMS], const int student)
    {
        int sum = 0;
    
        for (int i = 0; i < EXAMS; i++)
            sum += scores[student][i];
        
        return sum / EXAMS;
    }
    
    
    
    
    void printResults(int scores[][EXAMS], int students)
    {
        getScores(scores, students);
    
        for(int j = 0; j < students; j++)
        {   
            int sum = 0;
            cout << "The student with test scores ";
            for (int i = 0; i < EXAMS; i++)
            {
                if (i == EXAMS - 1)
                    cout << "and " << scores[j][i] << ", ";
                else
                    cout << scores[j][i] << ", ";
            }
            cout << "scored a final average of " << getAverage(scores, j) << " and earned a(n) " << getGrade(getAverage(scores, j)) << endl;
        }
}
nill9090
  • 3
  • 2
  • 1
    Note that your posted code would be easier to read (both for yourself and for other people) if you used consistent indentation. – Andreas Wenzel Oct 03 '22 at 01:42
  • Although this solution works, this is not the way the assignment is supposed to be solved. In the code comments to `getAverage` (which were probably supplied by the task assignment), it is stated that the second function argument should specify the length of the array. However, you are instead using that argument as the index number of the student, thereby violating the requirements of the assignment. See my answer for a solution which complies with the requirements of the assignment. – Andreas Wenzel Oct 03 '22 at 01:59
0

In the comments section of your question, you stated that the line

int getAverage(int scores[][EXAMS], const int students)

was written by you and not provided by the assignment.

However, according to the code comments above the function definition (which I assume were provided by the assignment and not written by you), the function should only deal with a 1D array, i.e. a sub-array of the 2D array. Therefore, you should change the function signature to the following:

int getAverage( int scores[], int students )

Due to array to pointer decay (arrays themselves are not passed to functions, only pointers to arrays), this is equivalent to the following:

int getAverage( int *scores, int students )

Since the size of the array is passed to the function, the function should take this size into account. Therefore, the function should be rewritten like this:

int getAverage( int scores[], int students )
{
    int sum = 0;

    for ( int i = 0; i < students; i++ )
    {
        sum += scores[i];
    }

    return sum / students;
}

Now that the function getAverage only accepts a 1D array instead of a 2D array, the function call of getAverage in the function printResults should be rewritten to only pass a sub-array of the 2D array, instead of the entire 2D array:

void printResults(int scores[][EXAMS], const int students)
{
    getScores(scores, students);

    for(int j = 0; j < students; j++)
    {
        cout << "The student with test scores ";
        for (int i = 0; i < EXAMS; i++)
        {
            if (i == EXAMS - 1)
                cout << "and " << scores[j][i] << ", ";
            else
                cout << scores[j][i] << ", ";
        }
        cout << "scored a final average of " << getAverage(scores[j], EXAMS) << " and earned a " << getGrade(getAverage(scores[j], EXAMS)) << endl;
    }
}

Note that it is not very efficient to call getAverage twice with the same arguments, because this means that the average must be computed twice. It would be better if you only called the function getAverage once and saved the result in a variable. However, as far as I can tell, your assignment restrictions forbid declaring another variable, so you cannot follow this recommendation in this case.

It is also worth noting that it is common practice to use i as the loop counter of the outer loop and j as the loop counter of the inner loop. You are doing the opposite in your case, which is confusing for most programmers reading your code.

Additionally, even if this code works, it would probably be more logical to call the function getScores in the function main, instead of the function printResults. This is because the function name printResults implies that the function will only print the results, but not actually calculate the results.

Therefore, if the restrictions on your assignment allow it, I would recommend removing the function call to getScores from the function printResults, and rewrite the function main like this:

int main() {
    const int STUDENTS = 5;
    int scores[STUDENTS][EXAMS] = {0};

    getScores(scores, STUDENTS);
    printResults(scores, STUDENTS);

    cout << endl;
    system("pause"); // for Visual Studio only

    return 0;
}
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • Thank you, the answer works. The main thing I was looking for was how to pass only a subarray of de 2d array which you explained well. – nill9090 Oct 04 '22 at 06:07