Please send questions to
st10@humboldt.edu .
/*--------------------------------------------------------
Implementation file for class Course with NO explicitly-
declared destructor, copy constructor, or overloaded
assignment operator.
created by: Sharon Tuttle
last modified: 12-12-03
---------------------------------------------------------*/
#include <iostream>
#include <string>
#include "Course.h"
#include "Prof.h"
#include "Student.h"
using namespace std;
//-----
// implementation of constructors
//
// assumption: when a course is first created,
// no students are enrolled in it.
//-----
Course::Course() : courseNum(""), courseName(""), numEnrolled(0),
enrolled(NULL)
{
// there must be a better way...!
Prof emptyProf;
instructor = emptyProf;
}
Course::Course(string cNum, string cName) : courseNum(cNum),
courseName(cName), numEnrolled(0),
enrolled(NULL)
{
// there must be a better way...!
Prof emptyProf;
instructor = emptyProf;
}
Course::Course(string cNum, string cName, Prof instr) : courseNum(cNum),
courseName(cName), numEnrolled(0),
enrolled(NULL), instructor(instr)
{
}
//-----
// implementation of copy constructor
//-----
//-----
// implementation of destructor
//-----
//-----
// implementation of accessors
//-----
string Course::get_courseName() const
{
return courseName;
}
string Course::get_courseNum() const
{
return courseNum;
}
int Course::get_numEnrolled() const
{
return numEnrolled;
}
Student* Course::get_enrolled() const
{
return enrolled;
}
Prof Course::get_instructor() const
{
return instructor;
}
//-----
// implementation of mutators
//
// assumption: users can only change numEnrolled
// and enrolled by enrolling, removing
// students from the course.
//-----
void Course::set_courseNum(string new_cNum)
{
courseNum = new_cNum;
}
void Course::set_courseName(string new_cName)
{
courseName = new_cName;
}
void Course::set_instructor(Prof new_instr)
{
instructor = new_instr;
}
//-----
// implementation of overloaded operators
//-----
bool Course::operator ==(const Course& rightHandCourse) const
{
// see if "easy to compare" fields are equal...
if ((courseNum == rightHandCourse.courseNum) &&
(courseName == rightHandCourse.courseName) &&
(numEnrolled == rightHandCourse.numEnrolled) &&
(instructor == rightHandCourse.instructor))
{
// if get here --- only students enrolled still need
// to be checked for equality
for (int i=0; i < numEnrolled; i++)
{
if (! (enrolled[i] == rightHandCourse.enrolled[i]))
{
return false;
}
}
// if make it out of loop without returning,
// then all students in enrolled are equivalent,
// too;
return true;
}
else
{
// if get here --- one of "easy to compare" fields
// wasn't equivalent
return false;
}
}
//-----
// implementation of other methods
//-----
//-----
// Contract: enroll : Student -> bool
// Purpose: try to add Student st to enrolled array for
// the calling Course. If numEnrolled ==
// ENROLLMENT_MAX, st cannot be added,
// and false is returned. Otherwise, st is
// added to the enrolled array (as its last element),
// and numEnrolled increases by one.
//
// Examples: if Course c1 has c1.numEnrolled == ENROLLMENT_MAX,
// and if st1 is a Student instance, then
// c1.enroll(st1) == false
// if Course c2 has c2.numEnrolled == 29
// and if st1 is a Student instance, then
// c2.enroll(st1) == true
// c2.numEnrolled == 30
// c2.enrolled[29] == st1
//-----
bool Course::enroll(Student st)
{
// cannot add st if class is full
if (numEnrolled == ENROLLMENT_MAX)
{
return false;
}
// if get here --- class is NOT full, can enroll this student!
// if class is currently empty, allocate a new gradesArray
// (it will be of size ENROLLMENT_MAX, but class will
// carefully make sure that only its elements
// 0 .. (numEnrolled-1) are considered enrolled Students)
if (numEnrolled == 0)
{
enrolled = new Student[ENROLLMENT_MAX];
}
// add the new student to the end of the "filled"
// portion of enrolled array
//
// do you see that, with numEnrolled "actual"
// students in enrolled, this new student
// will have index numEnrolled (which should then
// be incremented to reflect the new addition)?
enrolled[numEnrolled] = st;
numEnrolled++;
return true;
}
//-----
// Contract: remove : Student -> bool
// Purpose: try to remove Student st from enrolled array for
// the calling Course. If a Student equivalent
// to st cannot be found in enrolled, then returns
// false and nothing is changed. If such an
// equivalent st can be found, the first instance
// of such a Student will be removed from enrolled,
// the numEnrolled will be decreased by 1, and
// true will be returned.
//
// (If numEnrolled goes to 0, will deallocate
// enrolled array and make it NULL...)
//
// Examples: if Course c1 has enrolled NOT containing
// a Student equivalent to st1, where
// st1 is a Student instance, then
// c1.remove(st1) == false
// if Course c2 has c2.numEnrolled == 29
// and st1 has an equivalent instance in c2's
// enrolled array, then:
// c2.remove(st1) == true
// c2.numEnrolled == 28
// c2.enrolled has one fewer element (one fewer
// st1-equivalent Student)
//-----
bool Course::remove(Student st)
{
bool notFound = true;
int i = 0;
// try to look for student st in enrolled
while (notFound)
{
if (! (enrolled[i] == st))
{
i++;
}
else // found first instance of st!
{
notFound = false;
// if this is ONLY st in array, simply deallocate
// enrolled
if (numEnrolled == 1)
{
delete [] enrolled;
enrolled = false;
}
// otherwise, "remove" student by shifting all students
// to the right of this student by one position to
// the left
else
{
for (int j=i+1; j < numEnrolled; j++)
{
enrolled[j-1] = enrolled[j];
}
}
// interestingly enough, we can simply ignore
// the old "last element" student now;
// it cannot be accessed by Course's member
// functions...
// ...as long as we remember to update numEnrolled!
numEnrolled--;
return true;
}
}
// if get here: st isn't here to remove.
return false;
}
//-----
// Contract: void -> void
// Purpose: print a roll report for the calling Course
//
// Examples: for Prof p1("Tuttle", "Sharon", "M.", "Dr.", ...)
// and Student s1("Jones", "Anna", 3)
// Student s2("Smith", "Joe", 3)
// Student s3("Nguyen", "Dian", 3)
// and Course c1("CS 131", "Intro to CS", p1);
// c1.enroll(s1);
// c1.enroll(s2);
// c1.enroll(s3);
// Then c1.printRoll() should produce:
//
// Class Roll for CS 131 - Intro to CS:
//
// Instructor: Dr. Sharon M. Tuttle
// Enrollment: 3
// 1. Anna Jones
// 2. Joe Smith
// 3. Dian Nguyen
//------------------------------------------------------------
void Course::printRoll() const
{
// print header of class roll
cout << endl;
cout << "Class Roll for " << courseNum << " - " << courseName
<< ":" << endl;
cout << endl;
cout << "Instructor: " << instructor.mailingName() << endl;
cout << "Enrollment: " << numEnrolled << endl;
// print list of students in course
for (int i = 0; i < numEnrolled; i++)
{
cout << (i+1) << ". " << enrolled[i].get_firstName()
<< " " << enrolled[i].get_lastName() << endl;
}
cout << endl;
}
//-----
// Contract : courseAvg : void -> double
// Purpose : compute and return the course average
// by averaging the enrolled Students'
// current averages. If a student's
// current average is computed as -1,
// do not include it in the course
// average (and only divide by the
// number of students with non-neg-1
// averages). If no students have non-neg-1
// averages, return a course average of -1.
//
// Examples: for Student s1("Jones", "Anna", 3)
// with grades 100, 80, 75,
// Student s2("Smith", "Joe", 3)
// with no grades
// Student s3("Nguyen", "Dian", 3)
// with grades 60, 80, 90
// and Course c1("CS 131", "Intro to CS", p1);
// c1.enroll(s1);
// c1.enroll(s2);
// c1.enroll(s3);
// Then c1.courseAvg() == (approx) 80.83333
//
// For Course c2("CS 0", "Empty");
// c2.courseAvg() == -1
//
// For Course c3("CS 1", "Almost empty");
// Student s4("Johnson", "Ann", 0);
// Student s5("Jimson", "Benny", 0);
// Student s6("Judd", "Ashley", 3);
// c3.enroll(s4);
// c3.enroll(s5);
// c3.enroll(s6);
// then c3.courseAvg() == -1
//-----------------------------------------------------------
double Course::courseAvg() const
{
int numWiAvg = 0;
double sumAvgs = 0;
double currAvg;
for (int i=0; i < numEnrolled; i++)
{
// if this is "really" an average, count
// it and save its value;
currAvg = enrolled[i].avgGrade();
if (currAvg != -1)
{
numWiAvg++;
sumAvgs += currAvg;
}
// otherwise, ignore it;
}
// return -1 if NO student had grades!
if (numWiAvg == 0)
{
return -1;
}
else
{
return sumAvgs / numWiAvg;
}
}