Okay so I have a program that takes in up to 25 students and information for each including 5 test scores. All of that is done and working fine.

What I am trying to do now is calculate the averages of each test 1-5 and then the total average of the individual student's test averages.

for example:

Test1   Test2  Test3  Test4  Test5  Average
Student1 100     85     100    99     76     92.0
Student2 76      88     96     87     92     87.8

Average: 88.0    86.5   98.0   93.0   84.0   89.9 <--- This whole line is what I'm asking for help on

Here's my code so far:

HEADER:

using namespace std;
#ifndef STUDENT_CLASS
#define STUDENT_CLASS
class Student
{
    private:
            //Data Declaration
            int studentId;
            string firstName;
            string lastName;
            int *scores;
            double average;
            char grade;
            
            static int count;
            
            double calcAverage();
            
    public:
           //Default Constructor
           Student();
           //Deconstructor
           ~Student();
              
            //Set Declarations     
            void setId(int sX);
            void setFirst(string fN);
            void setLast(string lN);
            void setAverage(double sA);
            void setScores(int sS, int i);
            
            //Get Declarations
            int getId() const;
            string getFirst() const;
            string getLast() const;
            int getScores(int i) { return scores[i]; };
            
            char getGrade();
            
            //Calc. average function
            double getAverage() const;
            
            //Counter functions
            static int getCount();
            static void addCount() { count++; };
            
            //Display Function
            string displayData();
};
#endif

IMPLEMENTATION:

#include<iostream>
#include<iomanip>
#include<string>
#include<sstream>

using namespace std;

#include "Student.h"

int Student :: count = 0;

//Default Constructor
Student::Student()
{
         studentId = 0;
         firstName = "";
         lastName = "";
         
         average = 0.0;
         grade = ' ';
         scores = new int[5];
         
         for(int i = 0; i < 5; i++)
         scores[i] = 0;
}

Student::~Student()
{
       delete [] scores;
}
// Stringstream display function
string Student :: displayData(void)
{
       calcAverage();
       getGrade();

       stringstream strstr;
       
       strstr << left << setw(5) << studentId 
              << right << setw(5) << lastName << ", "
              << left << setw(5) << firstName
              << right << setw(5) << scores[0] 
              << right << setw(5) << scores[1] 
              << right << setw(5) << scores[2]
              << right << setw(5) << scores[3] 
              << right << setw(5) << scores[4];
              strstr << fixed << showpoint << setprecision(1);
              strstr << right << setw(8) << average;
              
             strstr << right << setw(8) << grade;
              
              return strstr.str();
}

//================================Set Mutator Function declarations=============================================
void Student::setId(int sX)
{
     studentId = sX;
}

void Student::setFirst(string fN)
{
     firstName = fN;
}

void Student::setLast(string lN)
{
     lastName = lN;
}

void Student::setAverage(double sA)
{
     average = sA;
}

void Student::setScores(int sS, int i)
{
     scores[i] = sS;
}
//================================Get Accessor Function declarations=============================================
int Student::getId() const
{
    return studentId;
}

string Student::getFirst() const
{
       return firstName;
}

string Student::getLast() const
{
       return lastName;
}

double Student::getAverage() const
{
     return average;  
}

int Student::getCount()
{
    return count;
}

//Function to calculate average of test scores
double Student::calcAverage()
{
     average = (scores[0] + scores[1] + scores[2] + scores[3] + scores[4]) / 5.0;
}

char Student::getGrade()
{
     if(average >= 90.0)
     {
        grade = 'A';
     }
     
     else if(average >= 80.0)
     {
        grade = 'B';
     }
     
     else if(average >= 70.0)
     {
        grade = 'C';
     }
     
    else if(average >= 60.0)
     {
        grade = 'D';
     }
     
     else
        grade = 'F';
}

MAIN:

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

#include "Student.h"

const int MAX = 25;

//Function Prototypes
void printData(Student *userData, double avg[]);
void getData(Student *userData);
bool newStudent(Student *userData, int index);

int main(int argc, char *argv[])
{
    Student *userData;
    userData = new Student[MAX];
    
    double avg[5] = {0.0};
    
    getData(userData);
    
    printData(userData, avg);
    
    delete [] userData;
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

//Function to keep count of student object array
void getData(Student *userData)
{
     bool done = false;
     int index = Student::getCount();
     while (index < MAX && !done)
     {
           while(newStudent(userData, index))
           {
                 Student::addCount();
                 index++;
           }
           done = true;
     }

}

//Function to read keyboard entry data into student object
bool newStudent(Student *userData, int index)
{
     int sX;
     int sS;
     string fN;
     string lN;
     
     cout << "Students currently entered: " << index << endl;
     cout << "Enter student ID (ctrl-z to quit): ";
     cin >> sX;
     
     if(cin.eof())
     {
        system("cls");
        return false;
     }
        cin.ignore();
     
     cout << "Enter student's first name: ";
     getline(cin, fN);
     cout << "Enter student's last name: ";
     getline(cin, lN);
     
     (userData + index)->setId(sX);
     (userData + index)->setFirst(fN);
     (userData + index)->setLast(lN);
     
     cout << "Please enter 5 test scores (seperate with spaces): ";
     
     for(int i = 0; i < 5; i++)
     {
           cin >> sS;
           (userData + index)->setScores(sS,i);
     }
     system("cls");
     return true;
}

//Function to incorporate stringstream to display data on console
void printData(Student *userData, double avg[])
{    
     cout << left
          << setw(9) << "ID"
          << setw(12) << "Name"
          << setw(5) << "1"
          << setw(5) << "2"
          << setw(5) << "3"
          << setw(5) << "4"
          << setw(5) << "5"
          << setw(9) << "Average"
          << setw(7) << "Grade" << endl;
          
          
     for(int i = 0; i < Student::getCount(); i++)
     {
             cout << (userData + i)->displayData() << endl;
     }
     
      for(int i = 0; i < Student::getCount(); i++)
             {   
                  
                  for(int j = 0; j < 5; j++)
                          avg[j] = (avg[j] + (userData + i)->getScores(j)) / i;
 
            }
            
             cout << "\n" << endl;
             cout << "Average: "
                  << fixed << showpoint << setprecision(1)
                  << right
                  << setw(13) << avg[0]
                  << setw(5) << avg[1]
                  << setw(5) << avg[2]
                  << setw(5) << avg[3]
                  << setw(5) << avg[4] << endl;

}

Here's where I'm having trouble:

for(int i = 0; i < Student::getCount(); i++)
             {   
                  
                  for(int j = 0; j < 5; j++)
                          avg[j] = (avg[j] + (userData + i)->getScores(j)) / i;
 
            }
            
             cout << "\n" << endl;
             cout << "Average: "
                  << fixed << showpoint << setprecision(1)
                  << right
                  << setw(13) << avg[0]
                  << setw(5) << avg[1]
                  << setw(5) << avg[2]
                  << setw(5) << avg[3]
                  << setw(5) << avg[4] << endl;

}

This line without the (/ i) works as it should.

for(int j = 0; j < 5; j++)
   avg[j] = (avg[j] + (userData + i)->getScores(j)) / i;

It adds each test together (Let's say there's two students and both get a 100 on Test 1, it adds them totaling 200), but when I got to divide that number by the number of students entered, it doesn't work correctly.

I have also yet to figure out how to find the total average of each student's average.

Thanks a lot!

Dani AI

Generated

Two quick, concrete fixes.

First: the averaging bug is caused by dividing while you accumulate (your loop does avg = (avg + score) / i), which both divides by zero on the first iteration and weights previous totals incorrectly. As said, accumulate totals first, then divide once by the number of students. Also ensure you initialize your totals to zero and guard against dividing when the student count is zero.

Second: a pair of undefined-behavior bugs in the class. Student::calcAverage() and Student::getGrade() are declared to return values but their implementations never return anything. That must be fixed (either make them void or actually return the computed value). Also make getScores(int) a const accessor so you can call it from const contexts.

A compact, safe pattern to compute per-test averages and the average of student averages (not present in the thread) — accumulate per-test totals and each student’s average in one pass, then divide once:

double colTotals[5] = {0.0,0.0,0.0,0.0,0.0};
double sumOfStudentAvgs = 0.0;
int n = Student::getCount();

for (int s = 0; s < n; ++s) {
    int studentSum = 0;
    for (int t = 0; t < 5; ++t) {
        int score = (userData + s)->getScores(t);
        colTotals[t] += score;
        studentSum += score;
    }
    sumOfStudentAvgs += static_cast<double>(studentSum) / 5.0; // per-student average
}

if (n > 0) {
    for (int t = 0; t < 5; ++t) colTotals[t] /= static_cast<double>(n);   // per-test averages
    double avgOfAverages = sumOfStudentAvgs / static_cast<double>(n);     // average of student averages
    // print colTotals[0..4] and avgOfAverages
}

Final notes: make calcAverage() either return average or become void and explicitly call it before reading getAverage(). Initialize any arrays you pass into printData and always check n > 0 before dividing. For longer-term maintainability, consider std::array<int,5> or std::vector<Student> to avoid manual new/delete and improve clarity.

You main problem is the algorithm that you calculate a continuous average with:
you do this:

for(int i = 0; i < Student::getCount(); i++)  
  for(int j = 0; j < 5; j++)
    avg[j] = (avg[j] + (userData + i)->getScores(j)) / i;

So what that does is effectively divide by i each time. e.g consider only 2 students with scores 3,3,3,3,3 etc. You do: ave[j]=((3/0)+3)/1). Obviously from that
expression you will get infinity.

The correct way to calculate an average, is to accumulate a total, and then divide by the number of students.

for(int j=0;j < 5; j++)
       avg[j]=0.0;
     for(int i = 0; i < Student::getCount(); i++)
       for(int j = 0; j < 5; j++)
	 avg[j] += (userData + i)->getScores(j);;
     for(int j=0;j < 5; j++)
       avg[j]/=Student::getCount();
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.