8.10. GradeBook Case Study: Using a Rectangular Array In Section 8.8, we presented class GradeBook (Fig. 8.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 Rectangular Array in Class GradeBook Figure 8.17 contains a version of class GradeBook that uses a rectangular array grades to store the grades of several students on multiple exams. Each row of the array represents a single student's grades for the entire course, and each column represents a grade on one of the exams the students took during the course. An application such as GradeBookTest (Fig. 8.18) passes the array as an argument to the GradeBook constructor. In this example, we use a 10-by-3 array containing ten students' grades on three exams. Five methods perform various array manipulations to process the grades. Each method is similar to its counterpart in the earlier one-dimensional array version of class GradeBook (Fig. 8.13). Method GetMinimum (lines 4561) determines the lowest grade of any student for the semester. Method GetMaximum (lines 6480) determines the highest grade of any student for the semester. Method GetAverage (lines 8393) determines a particular student's semester average. Method OutputBarChart (lines 96126) outputs a bar chart of the distribution of all student grades for the semester. Method OutputGrades (lines 129156) outputs the rectangular array in a tabular format, along with each student's semester average. Figure 8.17. GradeBook class using a rectangular array to store grades. 1 ' Fig. 8.17: GradeBook.vb 2 ' Grade book using a rectangular array to store grades. 3 Public Class GradeBook 4 Private courseNameValue As String ' name of course 5 Private grades As Integer(,) ' rectangular array of student grades 6 7 ' two-argument constructor initializes courseNameValue and Grades 8 Public Sub New(ByVal name As String, ByVal gradesArray As Integer(,)) 9 CourseName = name ' initializes courseNameValue via property 10 grades = gradesArray ' store grades 11 End Sub ' New 12 13 ' property CourseName 14 Public Property CourseName() As String 15 Get 16 Return courseNameValue 17 End Get 18 19 Set(ByVal name As String) 20 courseNameValue = name 21 End Set 22 End Property 'Course Name 23 24 ' display a welcome message to the GradeBook user 25 Public Sub DisplayMessage() 26 Console.WriteLine("Welcome to the grade book for " & vbCrLf &_ 27 CourseName & vbCrLf) 28 End Sub ' DisplayMessage 29 30 ' perform various operations on the data 31 Public Sub ProcessGrades() 32 OutputGrades() 'output grades array 33 34 ' call methods GetMinimum and GetMaximum 35 Console.WriteLine("Lowest grade in the grade book is {0}",_ 36 GetMinimum()) 37 Console.WriteLine("Highest grade in the grade book is {0}",_ 38 GetMaximum()) 39 40 'call OutputBarChart to print grade distribution chart 41 OutputBarChart() 42 End Sub 'ProcessGrades 43 44 'find minimum grade 45 Public Function GetMinimum() As Integer 46 'assume first element of grades array is smallest 47 Dim lowGrade As Integer=grades(0,0) 48 49 ' loop through grades array 50 For i As Integer = 0 To grades.GetUpperBound(0) 51 ' loop through columns of current row 52 For j As Integer = 0 To grades.GetUpperBound(1) 53 ' if grade lower than lowGrade, assign it to lowGrade 54 If grades(i,j) < lowGrade Then 55 lowGrade = grades(i,j) ' new lowest grade 56 End If 57 Next 58 Next 59 60 Return lowGrade ' return lowest grade 61 End Function ' GetMinimum 62 63 ' find maximum grade 64 Public Function GetMaximum() As Integer 65 'assume first element of grades array is largest 66 Dim highGrade As Integer = grades (0, 0) 67 68 'loop through grades array 69 For i As Integer = 0 To grades.GetUpperBound(0) 70 'loop through columns of current row 71 For j As Integer = 0 To grades.GetUpperBound(1) 72 'if grade greater than highGrade, assign it to highGrade 73 If grades(i,j) > highGrade Then 74 highGrade = grades(i,j) 'new highest grade 75 End If 76 Next 77 Next 78 79 Return highGrade 'return highest grade 80 End Function 'GetMaximum 81 82 'determine average grade for particular student's grades 83 Public Function GetAverage(ByVal row As Integer) As Double 84 Dim total As Integer = 0 'initialize total 85 86 'sum grades for one student 87 For column As Integer = 0 To grades.GetUpperBound(1) 88 total += grades(row, column) 89 Next 90 91 ' return average of grades 92 Return (total / (grades.GetUpperBound(1) +1)) 93 End Function ' GetAverage 94 95 'output bar chart displaying grade distribution 96 Public Sub OutputBarChart() 97 Console.WriteLine(vbCrLf & "Overall grade distribution:") 98 99 'stores frequency of grades in each range of 10 grades 100 Dim frequency As Integer() = New Integer(10){} 101 102 'for each grade, increment the appropriate frequency 103 For i As Integer = 0 To grades.GetUpperBound(0) 104 For j As Integer = 0 To grades.GetUpperBound(1) 105 frequency(grades(i,j)\10)+=1 106 Next 107 Next 108 109 'for each grade frequency, print bar in chart 110 For count As Integer = 0 To frequency.GetUpperBound(0) 111 'output bar label ("00-09:",..., "90-99: ", "100: ") 112 If count = 10 Then 113 Console.Write("{0, 5:D}:",100) 114 Else 115 Console.Write("{0, 2:D2}-{1, 2:D2}:",_ 116 count *10, count *10+9) 117 End If 118 119 'print bar of asterisks 120 For stars As Integer = 0 To frequency(count) -1 121 Console.Write("*") 122 Next 123 124 Console.WriteLine() 'start a new line of output 125 Next 126 End Sub 'OutputBarChart 127 128 'output the contents of the grades array 129 Public Sub OutputGrades() 130 Console.WriteLine("The grades are:" & vbCrLf) 131 Console.Write(" ") 'align column heads 132 133 'create a column heading for each of the tests 134 For test As Integer = 0 To grades.GetUpperBound(1) 135 Console.Write("Test {0:D} ", test + 1) 136 Next 137 138 Console.WriteLine("Average") ' student average column heading 139 140 ' create rows/columns of text representing array grades 141 For student As Integer = 0 To grades.GetUpperBound(0) 142 Console.Write("Student{0, 2:D}", student+1) 143 144 'output student's grades 145 For counter As Integer = 0 To grades.GetUpperBound(1) 146 Console.Write("{0, 8:D}", grades(student, counter)) 147 Next 148 149 'call method GetAverage to calculate student's average grade; 150 'pass row of grades as the argument to GetAverage 151 Dim average As Double = GetAverage(student) 152 Console.WriteLine("{0, 9:F2}", average) 153 Next 154 155 Console.WriteLine() 156 End Sub ' OutputGrades 157 End Class ' GradeBook | Figure 8.18. Creating a GradeBook object using a rectangular array of grades, then invoking method processGrades to analyze them. 1 ' Fig. 8.18: GradeBookTest.vb 2 ' Create GradeBook object using a rectangular array of grades. 3 Module GradeBookTest 4 Sub Main() 5 ' array of student grades 6 Dim gradesArray As Integer(,) 7 gradesArray = New Integer(,) {{87, 96, 70}, {68, 87, 90}, _ 8 {94, 37, 90}, {100, 81, 82}, {83, 65, 85}, {78, 87, 65}, _ 9 {85, 75, 83}, {91, 59, 100}, {76, 72, 84}, {87, 93, 73}} 10 11 Dim gradeBooks As New GradeBook( _ 12 "CS101 Introduction to Visual Basic Programming", gradesArray) 13 gradeBooks.DisplayMessage() 14 gradeBooks.ProcessGrades() 15 End Sub ' Main 16 End Module ' GradeBookTest Welcome to the grade book for CS101 Introduction to Visual Basic 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 37 90 73.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 59 100 83.33 Student 9 76 72 84 77.33 Student 10 87 93 73 84.33 Lowest grade in the grade book is 37 Highest grade in the grade book is 100 Overall grade distribution: 00-09: 10-19: 20-29: 30-39: * 40-49: 50-59: * 60-69: *** 70-79: ****** 80-89: *********** 90-99: ****** 100: ** |
| Methods GetMinimum, GetMaximum, OutputBarChart and OutputGrades each loop through array grades by using nested For statementsfor example, the nested For statement (lines 5058) from the declaration of method GetMinimum. The outer For statement iterates through the rows of two-dimensional array grades. To find the lowest overall grade, the inner For statement compares the current array element to variable lowGrade. For example, on the first iteration of the outer For, row 0 of grades is used. The inner For statement then loops through elements in row 0 and compares each grade value with lowGrade. If a grade is less than lowGrade, lowGrade is set to that grade. On the second iteration of the outer For statement, row 1 of grades is used, and the elements of this row are compared with variable lowGrade. This repeats until all the rows of grades have been traversed. When execution of the nested statement is complete, lowGrade contains the lowest grade in the two-dimensional array. Method GetMaximum works similarly to method GetMinimum. Method OutputBarChart in Fig. 8.17 is nearly identical to the one in Fig. 8.13. However, to output the overall grade distribution for a whole semester, the method here uses a nested For statement (lines 103107) to create the one-dimensional array frequency based on all the grades in the rectangular array. The rest of the code in each of the two OutputBarChart methods that displays the chart is identical. Method OutputGrades (lines 129156) also uses nested For statements to output values of the array grades, in addition to each student's semester average. The output in Fig. 8.18 shows the result, which resembles the tabular format of a professor's physical grade book. Lines 134136 (Fig. 8.17) print the column headings for each test. We use a counter-controlled For statement here so that we can identify each test with a number. Similarly, the For statement in lines 141153 first outputs a row label using a counter variable to identify each student (line 142). Although array indices start at 0, note that lines 135 and 142 output test + 1 and student + 1, respectively, to produce test and student numbers starting at 1 (see Fig. 8.18). The inner For statement in lines 145147 loops through a specific row of array grades and outputs each student's test grades. Finally, line 151 obtains each student's semester average by passing the current row number (i.e., student) to method GetAverage. Method GetAverage (lines 8393) takes one argumentan integer which specifies the row number of a particular student. When line 151 calls GetAverage, the argument is student, which specifies that a particular row number of the rectangular array grades should be passed to GetAverage. Method 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 92). Class GradeBookTest That Demonstrates Class GradeBook The application in Fig. 8.18 creates an object of class GradeBook (Fig. 8.17) using the rectangular array of Integers named gradesArray (declared and initialized in lines 69). Lines 1112 pass a course name and gradesArray to the GradeBook constructor. Lines 1314 then invoke gradeBooks's DisplayMessage and ProcessGrades methods to display a welcome message and obtain a report summarizing the students' grades for the semester, respectively. |