home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C++ for Dummies (3rd Edition)
/
C_FD.iso
/
WORKOUT
/
PART3.TXT
< prev
next >
Wrap
Text File
|
1996-09-06
|
11KB
|
307 lines
25-Minute Workout
Part III Answer
HereÆs my analysis of the problem. The two classes I chose from the description were Course and Student.
Armed with these candidate classes, I returned to the problem description to look for verbs to be turned
into member functions. I found the following:
* Students enroll in courses
* Students are graded
* The program averages all grades in each course
* The program returns each studentÆs grade in each course
* The program averages each studentÆs grades from all courses in which that student is
enrolled
* The program calculates the average curved grade by the average grade in the class
To enroll a student in a course and perform the necessary averages, I concluded that each Student object
needed to know what courses it was enrolled in (like a course list) and each Course needed to know what
students it had (like a student roll). To keep things simple, I used an array and set a maximum number of
courses per student and a maximum number of students in each course. So that these maximums were not
exceeded, I also needed noStudents to class Course and noCourses to Student.
I needed also a Student::add(Course&) to add a course to the studentÆs course list and a
Course::add(Student&) to add the student to the courseÆs student roll. These two functions handled the
enroll verb mentioned in the preceding list.
It wasnÆt important to me whether the application accessed these two functions through the Student class or
the Course class; I chose Student. To keep me from forgetting and getting it wrong in use, I made
Course::add() protected.
The Students are graded item in the preceding list implied the need for a grade function in Student or
Course. Is the grade a student receives in a course a property of the student or a property of the course? I
couldnÆt find a good answer to that one, except that historically grades are kept in little books (or little
computer databases, nowadays) associated with the course. Thus, I decided to add the member function
Course::grade(Student&, grade). I also added member functions grade(Student&) to return a studentÆs
grade and grade() to return the average of all students in the course, as stipulated by the requirements.
One final member function in Course, findStudent(), is used in several member functions to find a student
in the roll. These functions which are needed only internally should be left protected to keep the classÆs
surface area as small as possible.
Semester hours is obviously a property of Course, requiring a data member and a member function to set it.
The studentÆs name is a property of Student, requiring a data member and function pair as well.
The following is my solution to the problem along with a description of how it works. Realize that your
solution may be different; there is no single right solution as long as youÆre trying to think like an object.
//PROB3.CPP My solution to the Part III Workout
#include <iostream.h>
#include <string.h>
const int maxStudents = 20; //max no. of students in one class
const int maxCourses = 6; //max no. of courses student can take
class Student; //Note 1
class Course
{
friend class Student;
public:
Course( ) //Note 2
{
noStudents = 0;
semesterHours = 3; //default is 3
}
~Course( )
{
//nothing to do here
}
//hours - return or set the number of hours in this class
int hours( )
{
return semesterHours;
}
int hours(int newValue)
{ //Note 3
int oldValue = semesterHours; //itÆs customary to...
semesterHours = newValue;
return oldValue; //...return old value
}
//grade - return the average for the class or the grade of a
// single student or set the grade of a single student
float grade( ); //Note 4
float grade(Student &s);
void grade(Student &s, float grade);
protected:
//member functions
//add - add a student to the roll
int add(Student &s);
//findStudent - find student in role
int findStudent(Student &s);
//data members
Student *pStudents[maxStudents];
float classGrade[maxStudents];
int semesterHours;
int noStudents;
};
class Student
{
public:
Student( )
{
//just zero out everything
noCourses = 0;
sName[0] = æ\0Æ;
}
~Student( )
{
//nothing to do
}
//return grade in a given course or average in all courses
float grade(Course &c) //Note 5
{
return c.grade(*this);
}
float grade( );
//return the grade compared to the class average
float curvedGrade(Course &c);
//add a student to a course
void add(Course &c);
//name - read and set name
char *name( )
{
return sName;
}
void name(char *pName);
protected:
char sName[20];
Course *pClasses[maxCourses];
int noCourses;
};
//--------------Course member functions---------------------
//grade - return the average for the class
float Course::grade( )
{
//if there are no students, forget it now
if (noStudents == 0)
{
return 0.0F;
}
//add æem all and return the average
float accumGrade = 0.0F;
for (int i = 0; i < noStudents; i++)
{
accumGrade += classGrade[i];
}
return accumGrade / noStudents;
}
//grade(Student*) - return the grade of a single student
float Course::grade(Student &s)
{
//first look the student up in the student roll
int offset = findStudent(s);
//return studentÆs grade or 0 if the student wasnÆt found
return (offset >= 0) ? classGrade[offset] : 0.0F;
}
//grade(Student, grade) - set the grade of a single student
void Course::grade(Student &s, float grade)
{
int offset = findStudent(s);
if (offset >= 0)
{
classGrade[offset] = grade;
}
}
//add - add a student to the class roll; return 1 if
// it works and a zero otherwise
int Course::add(Student &s)
{
if (noStudents >= maxStudents)
{
cout << ôNo more room in class...maybe next semester\nö;
return 0;
}
pStudents[noStudents++] = &s;
return 1;
}
//findStudent - find a student in the look-up table;
// return offset or -1 if canÆt find
int Course::findStudent(Student &s)
{
for (int i = 0; i < noStudents; i++)
{
if (pStudents[i] == &s)
{
return i;
}
}
return -1;
}
//--------------Student member functions-------------------
//grade( ) - return the average grade for all courses
float Student::grade( )
{
int hours;
int noHours = 0;
float accumGrade = 0.0F;
for (int i = 0; i < noCourses; i++)
{
hours = pClasses[i]->hours( );
accumGrade += pClasses[i]->grade(*this) * hours;
noHours += hours;
}
return (noHours) ? (accumGrade / noHours): 0.0F;
}
//add - add a student to a class
void Student::add(Course &c)
{
if (noCourses >= maxCourses)
{
cout << ôno more room in the inn\nö;
return;
}
if (c.add(*this))
{
pClasses[noCourses++] = &c;
}
}
//curvedGrade - return the grade curved by the average
float Student::curvedGrade(Course &c)
{
//set the average to 3.0
float g = 3.0F * grade(c) / c.grade( );
//donÆt let it go over 4.0
if (g > 4.0F)
{
g = 4.0F;
}
return g;
}
//name(char*) - store the name provided
void Student::name(char *pName)
{
strncpy(sName, pName, sizeof(sName) - 1);
sName[sizeof(sName) - 1] = æ\0Æ;
}
//--------------------test program-------------------------
int main( )
{
//declare a course
Course geo101;
//give it a couple of students
Student harry, anne;
harry.name(ôHarryö);
harry.add(geo101);
anne.name(ôAnneö);
anne.add(geo101);
//grade them
geo101.grade(harry, 3.0F);
geo101.grade(anne, 2.5F);
//now letÆs look at the ave