0

I'm trying to experiment with 2D arrays in C++ and I'm working on a project that makes a 4x4 2D array that holds a number of student grades but it is partially filled via a text file. Only 3 out of the 4 columns are filled. I want to filled the last column with an average of the grades in the previous rows of each column.

The problem is I can't figure out exactly how to fill the last column.

This my code for calculating the average.

const int SIZE = 4;

const int ROWS = 4;
const int COLS = 4;

int total = 0;

for (int i = 0; i < ROWS; i++)
{
    total = 0;

    for (int j = 0; j < COLS - 1; j++)
    {
        total += studentGrades[i][j];

        average = total / (COLS - 1);

        studentGrades[0][3] = average;
        studentGrades[1][3] = average;
        studentGrades[2][3] = average;
        studentGrades[3][3] = average;
    }
}

It seems like I'm close because I'm getting good results but the last column isn't displaying the right values and I feel like there's a more efficient way to fill the last column instead of manually inserting into each index.

Keyaki
  • 19
  • 3
  • 1
    `average = total / (COLS - 1);` is integer division. It will always return integers, so 10/3 would be equal to 3. See this question: [Why does dividing two int not yield the right value when assigned to double?](https://stackoverflow.com/questions/7571326/why-does-dividing-two-int-not-yield-the-right-value-when-assigned-to-double) – Yksisarvinen Jan 20 '19 at 20:28

2 Answers2

1

You are assigning the last computed average to all rows every time. This means at the end you will have the average of row 4 in all 4 columns. Also consider changing your variables (studentGrades and total) to a floating point type for more accuracy.

const int SIZE = 4;

const int ROWS = 4;
const int COLS = 4;

for (int i = 0; i < ROWS; i++)
{
    int total = 0;

    for (int j = 0; j < COLS - 1; j++)        
        total += studentGrades[i][j];

    studentGrades[i][COLS - 1] = total / (COLS - 1);
}

You could also make use of the standard library:

#include <numeric>

// ...

constexpr int Rows = 4, Cols = 4, NGrades = Cols - 1; 

for (int i = 0; i < Rows; i++)
    studentGrades[i][NGrades] = std::accumulate(studentGrades[i], studentGrades[i] + NGrades, 0) / NGrades;

As in my first solution, consider using floating point types. To enable float arithmetic change the 0 of std::accumulate to 0.0 or 0.0f.

Here is an explanation of std::accumulate.

Timo
  • 9,269
  • 2
  • 28
  • 58
1

The logic is wrong. You can only calculate the average and fill the last column after you have totaled the other columns, and you can only fill one row at a time, instead of trying to do all four rows together. This is the correct loop

for (int i = 0; i < ROWS; i++)
{
    total = 0;
    for (int j = 0; j < COLS - 1; j++)
    {
        total += studentGrades[i][j];
    }
    average = total / (COLS - 1);
    studentGrades[i][3] = average;
}

It's just a matter of doing things in the right order and at the right time.

Plus you should pay attention to the integer division problem that Yksisarvinen pointed out.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
john
  • 85,011
  • 4
  • 57
  • 81