7.9 Case Study: Class GradeBook Using a Two-Dimensional array

In Section 7.6, we presented class GradeBook (Fig. 7.13), 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

Figure 7.18 shows the output that summarizes 10 students’ grades on three exams. We store the grades as a two-dimensional array in an object of the next version of class GradeBook (Fig. 7.19). 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 Fig. 7.20, passes the array as an argument to the GradeBook constructor. Since there are 10 students and three exams, we use a ten-by-three array to store the grades.

Fig. 7.18 Output of GradeBook that uses two-dimensional arrays.

Alternate View

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: ***

Fig. 7.19 Definition of class GradeBook that uses a two-dimensional array to store test grades.

Alternate View

 1   // Fig. 7.19: GradeBook.h
 2   // Definition of class GradeBook that uses a
 3   // two-dimensional array to store test grades.
 4   #include <array>
 5   #include <string>
 6   #include <iostream>
 7   #include <iomanip> // parameterized stream manipulators
 8
 9   // GradeBook class definition
10   class GradeBook {
11   public:
12      // constants
13      static const size_t students{10}; // number of students  
14      static const size_t tests{3}; // number of tests        
15
16      // two-argument constructor initializes courseName and grades array
17      GradeBook(const std::string& name,
18         std::array<std::array<int, tests>, students>& gradesArray)
19         : courseName(name), grades(gradesArray) {
20      }
21
22      // function to set the course name
23      void setCourseName(const std::string& name) {
24         courseName = name; // store the course name
25      }
26
27      // function to retrieve the course name
28      const std::string& getCourseName() const {
29         return courseName;
30      }
31
32      // display a welcome message to the GradeBook user
33      void displayMessage() const {
34         // call getCourseName to get this GradeBook’s course name
35         std::cout << "Welcome to the grade book for
" << getCourseName()
36            << "!" << std::endl;
37       }
38
39      // perform various operations on the data
40      void processGrades() const {
41         outputGrades(); // output grades array
42
43         // call functions getMinimum and getMaximum
44         std::cout << "
Lowest grade in the grade book is " << getMinimum()
45            << "
Highest grade in the grade book is " << getMaximum()
46            << std::endl;
47
48         outputBarChart(); // display grade distribution chart
49      }
50
51      // find minimum grade in the entire gradebook
52      int getMinimum() const {
53         int lowGrade{100}; // assume lowest grade is 100
54
55         // loop through rows of grades array
56         for (auto const& student : grades) {
57            // loop through columns of current row
58            for (auto const& grade : student) {
59               if (grade < lowGrade) { // if grade is lower than lowGrade
60                  lowGrade = grade; // grade is new lowest grade
61               }
62            }
63          }
64
65          return lowGrade; // return lowest grade
66      }
67
68     // find maximum grade in the entire gradebook
69     int getMaximum() const {
70        int highGrade{0}; // assume highest grade is 0
71
72        // loop through rows of grades array
73        for (auto const& student : grades) {
74           // loop through columns of current row
75           for (auto const& grade : student) {
76              if (grade > highGrade) { // if grade is higher than highGrade
77                 highGrade = grade; // grade is new highest grade
78              }
79           }
80         }
81
82         return highGrade; // return highest grade
83      }
84
85      // determine average grade for particular set of grades
86      double getAverage(const std::array<int, tests>& setOfGrades) const {
87         int total{0}; // initialize total
88
89         // sum grades in array
90         for (int grade : setOfGrades) {
91            total += grade;
92         }
93
94         // return average of grades
95         return static_cast<double>(total) / setOfGrades.size();
96      }
97
98      // output bar chart displaying grade distribution
99      void outputBarChart() const {
100        std::cout << "
Overall grade distribution:" << std::endl;
101
102        // stores frequency of grades in each range of 10 grades
103        const size_t frequencySize{11};
104        std::array<unsigned int, frequencySize> frequency{}; // init to 0s
105
106        // for each grade, increment the appropriate frequency
107        for (auto const& student : grades) {
108           for (auto const& test : student) {
109              ++frequency[test / 10];
110           }
111         }
112
113         // for each grade frequency, print bar in chart
114         for (size_t count{0}; count < frequencySize; ++count) {
115            // output bar label ("0-9:", ..., "90-99:", "100:")
116            if (0 == count) {
117               std::cout << " 0-9: ";
118            }
119            else if (10 == count) {
120               std::cout << " 100: ";
121            }
122            else {
123               std::cout << count * 10 << "-" << (count * 10) + 9 << ": ";
124            }
125
126            // print bar of asterisks
127            for (unsigned int stars{0}; stars < frequency[count]; ++stars)
128               std::cout << '*';
129
130            std::cout << std::endl; // start a new line of output
131         }
132      }
133
134      // output the contents of the grades array
135      void outputGrades() const {
136         std::cout << "
The grades are:

";
137         std::cout << "            "; // align column heads
138
139         // create a column heading for each of the tests
140         for (size_t test{0}; test < tests; ++test) {
141            std::cout << "Test " << test + 1 << "  ";
142         }
143
144         std::cout << "Average" << std::endl;
145
146         // create rows/columns of text representing array grades
147         for (size_t student{0}; student < grades.size(); ++student) {
148            std::cout << "Student " << std::setw(2) << student + 1;
149
150            // output student's grades
151            for (size_t test{0}; test < grades[student].size(); ++test) {
152               std::cout << std::setw(8) << grades[student][test];
153            }
154
155            // call member function getAverage to calculate student's
156            // average; pass one row of grades as the argument
157            double average{getAverage(grades[student])};
158            std::cout << std::setw(9) << std::setprecision(2) << std::fixed
159               << average << std::endl;
160           }
161       }
162    private:
163       std::string courseName; // course name for this grade book
164       std::array<std::array<int, tests>, students> grades; // 2D array
165    };

Overview of Class GradeBook’s Functions

Each of class GradeBook’s member functions is similar to its counterpart in the earlier one-dimensional array version of class GradeBook (Fig. 7.13). Member function getMinimum (lines 52–66 of Fig. 7.19) determines the lowest grade of all students for the semester. Member function getMaximum (lines 69–83) determines the highest grade of all students for the semester. Member function getAverage (lines 86–96) determines a particular student’s semester average. Member function outputBarChart (lines 99–132) outputs a bar chart of the distribution of all student grades for the semester. Member function output-Grades (lines 135–161) outputs the two-dimensional array in a tabular format, along with each student’s semester average.

Functions getMinimum and getMaximum

Member functions getMinimum, getMaximum, outputBarChart and outputGrades each loop through array grades by using nested range-based for or counter-controlled for statements. For example, consider the nested for statement (lines 56–63) in member function getMinimum. The outer for statement loops through the rows that represent each student and the inner for loops through the grades of a given student. Each grade is compared with variable lowGrade in the body of the inner for statement. If a grade is less than lowGrade, lowGrade is set to that grade. This repeats until all rows and columns 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.

Function outputBarChart

Member function outputBarChart in Fig. 7.19 is nearly identical to the one in Fig. 7.13. However, to output the overall grade distribution for a whole semester, the function uses a nested for statement (lines 107–111 in Fig. 7.19) to increment the elements of the one-dimensional array frequency, based on all the grades in the two-dimensional array. The rest of the code in the two outputBarChart member functions is identical.

Function outputGrades

Member function outputGrades (lines 135–161) uses nested counter-controlled for statements to output values of the array grades, in addition to each student’s semester average. The output in Fig. 7.18 shows the result, which resembles the tabular format of a professor’s physical grade book. Lines 140–142 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 147–160 first outputs a row label using a counter variable to identify each student (line 148). Although array indices start at 0, lines 141 and 148 output test + 1 and student + 1, respectively, to produce test and student numbers starting at 1 (see Fig. 7.18). The inner for statement in lines 151–153 of Fig. 7.19 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 157 obtains each student’s semester average by passing the current row of grades (i.e., grades[student]) to member function getAverage.

Function getAverage

Member function getAverage (lines 86–96) takes as an argument a one-dimensional array of test results for a particular student. When line 157 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.20, 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’s rows 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 (Fig. 7.19, line 95).

Testing Class GradeBook

The program in Fig. 7.20 creates an object of class GradeBook (Fig. 7.19) using the two-dimensional array of ints named grades (declared and initialized in lines 9–19 of Fig. 7.20). Line 9 accesses class GradeBook’s static constants students and tests to indicate the size of each dimension of array grades. Line 21 passes a course name and grades to the GradeBook constructor. Lines 22–23 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.

Fig. 7.20 Creates a GradeBook object using a two-dimensional array of grades, then invokes member function processGrades to analyze them.

Alternate View

 1   // Fig. 7.20: fig07_20.cpp
 2   // Creates GradeBook object using a two-dimensional array of grades.
 3   #include <array>
 4   #include "GradeBook.h" // GradeBook class definition
 5   using namespace std;
 6
 7   int main() {
 8      // two-dimensional array of student grades
 9      array<array<int, GradeBook::tests>, GradeBook::students> grades{
10         {87, 96, 70},
11         {68, 87, 90},
12         {94, 100, 90},
13         {100, 81, 82},
14         {83, 65, 85},
15         {78, 87, 65},
16         {85, 75, 83},
17         {91, 94, 100},
18         {76, 72, 84},
19         {87, 93, 73}};
20
21      GradeBook myGradeBook("CS101 Introduction to C++ Programming", grades);
22      myGradeBook.displayMessage();
23      myGradeBook.processGrades();
24   }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset