In Section 7.6, we presented class GradeBook (Figs. 7.167.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.237.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.
Five member functions (declared in lines 2327 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.167.17). Member function getMinimum (defined in lines 6582 of Fig. 7.24) determines the lowest grade of any student for the semester. Member function getMaximum (defined in lines 85102 of Fig. 7.24) determines the highest grade of any student for the semester. Member function getAverage (lines 105115 of Fig. 7.24) determines a particular student's semester average. Member function outputBarChart (lines 118149 of Fig. 7.24) outputs a bar chart of the distribution of all student grades for the semester. Member function outputGrades (lines 152177 of Fig. 7.24) outputs the two-dimensional array in a tabular format, along with each student's semester average.
Figure 7.23. Definition of class GradeBook with a two-dimensional array to store grades.
(This item is displayed on pages 365 - 366 in the print version)
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 // 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 ); // find average of grades 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 |
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 7079). 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 127130) 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.
Figure 7.24. GradeBook class member-function definitions manipulating a two-dimensional array of grades.
(This item is displayed on pages 366 - 369 in the print version)
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 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 using std::fixed; 9 10 #include // 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 " << 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 << " Lowest grade in the grade book is " << getMinimum() 58 << " Highest 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 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 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 << " Overall grade distribution:" << endl; 121 122 // stores frequency of grades in each range of 10 grades 123 const int frequencySize = 11; 124 int frequency[ frequencySize ] = { 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 << " The grades are: "; 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 |
Member function outputGrades (lines 152177) 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 158159 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 164176 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 169170 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.
Figure 7.25. Creates a GradeBook object using a two-dimensional array of grades, then invokes member function processGrades to analyze them.
(This item is displayed on pages 370 - 371 in the print version)
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
|
Member function getAverage (lines 105115) takes two argumentsa 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.237.24) using the two-dimensional array of ints named gradesArray (declared and initialized in lines 1020). Note that line 10 accesses class GradeBook's static constants students and tests to indicate the size of each dimension of array gradesArray. Lines 2223 pass a course name and gradesArray to the GradeBook constructor. Lines 2425 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.
Introduction to Computers, the Internet and World Wide Web
Introduction to C++ Programming
Introduction to Classes and Objects
Control Statements: Part 1
Control Statements: Part 2
Functions and an Introduction to Recursion
Arrays and Vectors
Pointers and Pointer-Based Strings
Classes: A Deeper Look, Part 1
Classes: A Deeper Look, Part 2
Operator Overloading; String and Array Objects
Object-Oriented Programming: Inheritance
Object-Oriented Programming: Polymorphism
Templates
Stream Input/Output
Exception Handling
File Processing
Class string and String Stream Processing
Web Programming
Searching and Sorting
Data Structures
Bits, Characters, C-Strings and structs
Standard Template Library (STL)
Other Topics
Appendix A. Operator Precedence and Associativity Chart
Appendix B. ASCII Character Set
Appendix C. Fundamental Types
Appendix D. Number Systems
Appendix E. C Legacy Code Topics
Appendix F. Preprocessor
Appendix G. ATM Case Study Code
Appendix H. UML 2: Additional Diagram Types
Appendix I. C++ Internet and Web Resources
Appendix J. Introduction to XHTML
Appendix K. XHTML Special Characters
Appendix L. Using the Visual Studio .NET Debugger
Appendix M. Using the GNU C++ Debugger
Bibliography