7.10. Case Study: Class GradeBook
Using a Two-Dimensional Array
In Section
7.6, we presented class GradeBook (Figs.
7.16–7.17), which used a one-dimensional array to store student
grades on a single exam. In most semesters, students take several exams.
Professors are likely to want to analyze grades across the entire semester, both
for a single student and for the class as a whole.
Storing Student Grades in a
Two-Dimensional Array in Class GradeBook
Figures
7.23–7.24 contain a version of class GradeBook that uses a two-dimensional array grades to store the grades of a number of students on multiple
exams. Each row of the array represents a single student's grades for the entire
course, and each column represents all the grades the students earned for one
particular exam. A client program, such as fig07_25.cpp, passes the array as an argument to the GradeBook
constructor. In this example, we use a ten-by-three array containing ten
students' grades on three exams.
Fig. 7.23. Definition of class GradeBook with a
two-dimensional array to store grades.
1 // Fig. 7.23: GradeBook.h
2 // Definition of class GradeBook that uses a
3 // two-dimensional array to store test grades.
4 // Member functions are defined in GradeBook.cpp
5 #include <string> // program uses C++ Standard Library string class
6 using std::string;
7
8 // GradeBook class definition
9 class GradeBook
10 {
11 public:
12 // constants
13 const static int students = 10; // number of students
14 const static int tests = 3; // number of tests
15
16 // constructor initializes course name and array of grades
17 GradeBook( string, const int [][ tests ] );
18
19 void setCourseName( string ); // function to set the course name
20 string getCourseName(); // function to retrieve the course name
21 void displayMessage(); // display a welcome message
22 void processGrades(); // perform various operations on the grade data
23 int getMinimum(); // find the minimum grade in the grade book
24 int getMaximum(); // find the maximum grade in the grade book
25 double getAverage( const int [], const int ); // get student's average
26 void outputBarChart(); // output bar chart of grade distribution
27 void outputGrades(); // output the contents of the grades array
28 private:
29 string courseName; // course name for this grade book
30 int grades[ students ][ tests ]; // two-dimensional array of grades
31 }; // end class GradeBook
|
Fig. 7.24. GradeBook class member-function
definitions manipulating a two-dimensional array of grades.
1 // Fig. 7.24: GradeBook.cpp
2 // Member-function definitions for class GradeBook that
3 // uses a two-dimensional array to store grades.
4 #include <iostream>
5 using std::cout;
6 using std::cin;
7 using std::endl;
8 using std::fixed;
9
10 #include <iomanip> // parameterized stream manipulators
11 using std::setprecision; // sets numeric output precision
12 using std::setw; // sets field width
13
14 // include definition of class GradeBook from GradeBook.h
15 #include "GradeBook.h"
16
17 // two-argument constructor initializes courseName and grades array
18 GradeBook::GradeBook( string name, const int gradesArray[][ tests ] )
19 {
20 setCourseName( name ); // initialize courseName
21
22 // copy grades from gradeArray to grades
23 for ( int student = 0; student < students; student++ )
24
25 for ( int test = 0; test < tests; test++ )
26 grades[ student ][ test ] = gradesArray[ student ][ test ];
27 } // end two-argument GradeBook constructor
28
29 // function to set the course name
30 void GradeBook::setCourseName( string name )
31 {
32 courseName = name; // store the course name
33 } // end function setCourseName
34
35 // function to retrieve the course name
36 string GradeBook::getCourseName()
37 {
38 return courseName;
39 } // end function getCourseName
40
41 // display a welcome message to the GradeBook user
42 void GradeBook::displayMessage()
43 {
44 // this statement calls getCourseName to get the
45 // name of the course this GradeBook represents
46 cout << "Welcome to the grade book for\n" << getCourseName() << "!"
47 << endl;
48 } // end function displayMessage
49
50 // perform various operations on the data
51 void GradeBook::processGrades()
52 {
53 // output grades array
54 outputGrades();
55
56 // call functions getMinimum and getMaximum
57 cout << "\nLowest grade in the grade book is " << getMinimum()
58 << "\nHighest grade in the grade book is " << getMaximum() << endl;
59
60 // output grade distribution chart of all grades on all tests
61 outputBarChart();
62 } // end function processGrades
63
64 // find minimum grade in the entire gradebook
65 int GradeBook::getMinimum()
66 {
67 int lowGrade = 100; // assume lowest grade is 100
68
69 // loop through rows of grades array
70 for ( int student = 0; student < students; student++ )
71 {
72 // loop through columns of current row
73 for ( int test = 0; test < tests; test++ )
74 {
75 // if current grade less than lowGrade, assign it to lowGrade
76 if ( grades[ student ][ test ] < lowGrade )
77 lowGrade = grades[ student ][ test ]; // new lowest grade
78 } // end inner for
79 } // end outer for
80
81 return lowGrade; // return lowest grade
82 } // end function getMinimum
83
84 // find maximum grade in the entire gradebook
85 int GradeBook::getMaximum()
86 {
87 int highGrade = 0; // assume highest grade is 0
88
89 // loop through rows of grades array
90 for ( int student = 0; student < students; student++ )
91 {
92 // loop through columns of current row
93 for ( int test = 0; test < tests; test++ )
94 {
95 // if current grade greater than lowGrade, assign it to highGrade
96 if ( grades[ student ][ test ] > highGrade )
97 highGrade = grades[ student ][ test ]; // new highest grade
98 } // end inner for
99 } // end outer for
100
101 return highGrade; // return highest grade
102 } // end function getMaximum
103
104 // determine average grade for particular set of grades
105 double GradeBook::getAverage( const int setOfGrades[], const int grades )
106 {
107 int total = 0; // initialize total
108
109 // sum grades in array
110 for ( int grade = 0; grade < grades; grade++ )
111 total += setOfGrades[ grade ];
112
113 // return average of grades
114 return static_cast< double >( total ) / grades;
115 } // end function getAverage
116
117 // output bar chart displaying grade distribution
118 void GradeBook::outputBarChart()
119 {
120 cout << "\nOverall grade distribution:" << endl;
121
122 // stores frequency of grades in each range of 10 grades
123 const int frequencySize = 11;
124 int frequency[ frequencySize ] = {}; // initialize elements to 0
125
126 // for each grade, increment the appropriate frequency
127 for ( int student = 0; student < students; student++ )
128
129 for ( int test = 0; test < tests; test++ )
130 ++frequency[ grades[ student ][ test ] / 10 ];
131
132 // for each grade frequency, print bar in chart
133 for ( int count = 0; count < frequencySize; count++ )
134 {
135 // output bar label ("0-9:", ..., "90-99:", "100:" )
136 if ( count == 0 )
137 cout << " 0-9: ";
138 else if ( count == 10 )
139 cout << " 100: ";
140 else
141 cout << count * 10 << "-" << ( count * 10 ) + 9 << ": ";
142
143 // print bar of asterisks
144 for ( int stars = 0; stars < frequency[ count ]; stars++ )
145 cout << '*';
146
147 cout << endl; // start a new line of output
148 } // end outer for
149 } // end function outputBarChart
150
151 // output the contents of the grades array
152 void GradeBook::outputGrades()
153 {
154 cout << "\nThe grades are:\n\n";
155 cout << " "; // align column heads
156
157 // create a column heading for each of the tests
158 for ( int test = 0; test < tests; test++ )
159 cout << "Test " << test + 1 << " ";
160
161 cout << "Average" << endl; // student average column heading
162
163 // create rows/columns of text representing array grades
164 for ( int student = 0; student < students; student++ )
165 {
166 cout << "Student " << setw( 2 ) << student + 1;
167
168 // output student's grades
169 for ( int test = 0; test < tests; test++ )
170 cout << setw( 8 ) << grades[ student ][ test ];
171
172 // call member function getAverage to calculate student's average;
173 // pass row of grades and the value of tests as the arguments
174 double average = getAverage( grades[ student ], tests );
175 cout << setw( 9 ) << setprecision( 2 ) << fixed << average << endl;
176 } // end outer for
177 } // end function outputGrades
|
Five member functions (declared in lines
23–27 of Fig. 7.23) perform array manipulations to process the grades. Each of
these member functions is similar to its counterpart in the earlier
one-dimensional array version of class GradeBook (Figs.
7.16–7.17).
Member function getMinimum (defined in lines 65–82 of Fig. 7.24)
determines the lowest grade of any student for the semester. Member function
getMaximum (defined in lines 85–102 of Fig. 7.24)
determines the highest grade of any student for the semester. Member function
getAverage (lines 105–115 of Fig. 7.24) determines a particular student's semester
average. Member function outputBarChart (lines 118–149 of Fig. 7.24) outputs a bar chart of the distribution of all student
grades for the semester. Member function outputGrades (lines 152–177 of
Fig. 7.24) outputs the two-dimensional array in a tabular format,
along with each student's semester average.
Member functions getMinimum, getMaximum,
outputBarChart and outputGrades each loop
through array grades by using nested for statements. For
example, consider the nested for statement in member function
getMinimum (lines 70–79). The outer for statement begins by
setting student (i.e., the row subscript) to 0, so the elements of
row 0 can be compared with variable lowGrade in the body of
the inner for statement. The inner for statement loops through the grades of a particular row
and compares each grade with lowGrade. If a grade is less than
lowGrade, lowGrade is set to that grade. The outer
for statement then increments the row subscript to 1. The elements of row 1 are compared with variable
lowGrade. The outer for statement
then increments the row subscript to 2, and the elements of row 2 are
compared with variable lowGrade. This repeats until all rows of
grades have been traversed. When execution of the nested statement is
complete, lowGrade contains the smallest grade in the two-dimensional
array. Member function getMaximum works similarly to member function
getMinimum.
Member function outputBarChart in Fig. 7.24 is nearly identical to the
one in Fig.
7.17. However, to output the overall grade
distribution for a whole semester, the member function uses a nested
for statement (lines 127–130) to create the
one-dimensional array frequency based on all
the grades in the two-dimensional array. The rest of the code in each of the two
outputBarChart member functions that
displays the chart is identical.
Member function outputGrades (lines
152–177) also uses nested for statements to
output values of the array grades, in addition to each student's
semester average. The output in Fig. 7.25
shows the result, which resembles the tabular format of a professor's physical
grade book. Lines 158–159 print the column headings for each test. We use a
counter-controlled for statement so that we can
identify each test with a number. Similarly, the for statement in lines 164–176 first outputs a row label using
a counter variable to identify each student (line 166). Although array indices
start at 0, note that lines 159 and 166 output test + 1 and student
+ 1, respectively, to produce test and student numbers starting at 1 (see
Fig. 7.25). The
inner for statement in lines 169–170 uses the outer for
statement's counter variable student to loop through a specific row of
array grades and output each student's test
grade. Finally, line 174 obtains each student's semester average by passing the
current row of grades (i.e., grades[ student
]) to member function getAverage.
Fig. 7.25. Creates a GradeBook object using a two-dimensional array of grades, then
invokes member function processGrades to analyze them.
1 // Fig. 7.25: fig07_25.cpp
2 // Creates GradeBook object using a two-dimensional array of grades.
3
4 #include "GradeBook.h" // GradeBook class definition
5
6 // function main begins program execution
7 int main()
8 {
9 // two-dimensional array of student grades
10 int gradesArray[ GradeBook::students ][ GradeBook::tests ] =
11 { { 87, 96, 70 },
12 { 68, 87, 90 },
13 { 94, 100, 90 },
14 { 100, 81, 82 },
15 { 83, 65, 85 },
16 { 78, 87, 65 },
17 { 85, 75, 83 },
18 { 91, 94, 100 },
19 { 76, 72, 84 },
20 { 87, 93, 73 } };
21
22 GradeBook myGradeBook(
23 "CS101 Introduction to C++ Programming", gradesArray );
24 myGradeBook.displayMessage();
25 myGradeBook.processGrades();
26 return 0; // indicates successful termination
27 } // end main
|
Welcome to the grade book for
CS101 Introduction to C++ Programming!
The grades are:
Test 1 Test 2 Test 3 Average
Student 1 87 96 70 84.33
Student 2 68 87 90 81.67
Student 3 94 100 90 94.67
Student 4 100 81 82 87.67
Student 5 83 65 85 77.67
Student 6 78 87 65 76.67
Student 7 85 75 83 81.00
Student 8 91 94 100 95.00
Student 9 76 72 84 77.33
Student 10 87 93 73 84.33
Lowest grade in the grade book is 65
Highest grade in the grade book is 100
Overall grade distribution:
0-9:
10-19:
20-29:
30-39:
40-49:
50-59:
60-69: ***
70-79: ******
80-89: ***********
90-99: *******
100: ***
|
Member function getAverage
(lines 105–115) takes two arguments—a one-dimensional array of test results for
a particular student and the number of test results in the array. When line 174
calls getAverage, the first argument is
grades[ student ], which specifies that a
particular row of the two-dimensional array grades should be passed to
getAverage. For example, based on the array created in Fig. 7.25, the argument grades[ 1
] represents the three values (a one-dimensional array of grades) stored in
row 1 of the two-dimensional array grades. A two-dimensional array can be considered an array
whose elements are one-dimensional arrays. Member function getAverage calculates the sum of the array elements, divides the
total by the number of test results and returns the floating-point result as a
double value (line 114).
Testing Class GradeBook
The program in Fig. 7.25 creates
an object of class GradeBook (Figs. 7.23–7.24) using the two-dimensional array
of ints named gradesArray (declared and initialized in lines
10–20). Note that line 10 accesses class GradeBook's static
constants students and tests to indicate the size of each
dimension of array gradesArray. Lines 22–23 pass a course name and
gradesArray to the GradeBook constructor. Lines 24–25 then
invoke myGradeBook's displayMessage and
processGrades member functions to
display a welcome message and obtain a report summarizing the students' grades
for the semester, respectively.
|
|
|
|
|