2. When the app executes, another compiler (known as the just-in-time compiler
8.11 Case Study: GradeBook Using a Rectangular Array
arrayreturns the size of the first dimension of the array (the number of rows), and the call
GetLength(1)returns the size of the second dimension (the number of columns).
MethodOutputArrayfor Jagged Arrays
Line 23 invokes methodOutputArraywith argumentjagged, so the version ofOutput-
Arrayat lines 43–56 is called. The nestedforeachstatement (lines 48–55) outputs the rows of a jagged array. The innerforeachstatement (lines 51–52) iterates through each element in the current row of the array. This allows the loop to determine the exact num- ber of columns in each row. Since the jagged array is created as an array of arrays, we can use nestedforeachstatements to output the elements in the console window. The outer loop iterates through the elements ofarray, which are references to one-dimensional ar- rays ofintvalues that represent each row. The inner loop iterates through the elements of the current row. Aforeachstatement can also iterate through all the elements in a rectan- gular array. In this case,foreachiterates through all the rows and columns starting from row0, as if the elements were in a one-dimensional array.
Common Multidimensional-Array Manipulations Performed withforStatements Many common array manipulations useforstatements. As an example, the followingfor statement sets all the elements in row 2 of rectangular arrayain Fig. 8.17 to0:
We specified row2; therefore, we know that the first index is always2(0is the first row, and1is the second row). Thisforloop varies only the second index (i.e., thecolumn in- dex). The precedingforstatement is equivalent to the assignment statements
The following nestedforstatement totals the values of all the elements in arraya:
These nestedforstatements total the array elements one row at a time. The outer for statement begins by setting therowindex to0so that row 0’s elements can be totaled by the innerforstatement. The outerforthen incrementsrowto1so that row 1’s elements can be totaled. Then the outerforincrementsrowto 2so that row 2’s elements can be totaled. The variabletotalcan be displayed when the outerforstatement terminates. In the next example, we show how to process a rectangular array in a more concise manner usingforeachstatements.
8.11 Case Study: GradeBook Using a Rectangular Array
In Section 8.9, we presented classGradeBook(Fig. 8.15), which used a one-dimensional array to store student grades on a single exam. In most courses, students take several exams.
for ( int column = 0; column < a.GetLength( 1 ); ++column ) a[ 2, column ] = 0;
a[ 2, 0 ] = 0;
a[ 2, 1 ] = 0;
a[ 2, 2 ] = 0;
a[ 2, 3 ] = 0;
int total = 0;
for ( int row = 0; row < a.GetLength( 0 ); ++row ) {
for ( int column = 0; column < a.GetLength( 1 ); ++column ) total += a[ row, column ];
} // end outer for
Instructors are likely to want to analyze grades across the entire course, both for a single student and for the class as a whole.
Storing Student Grades in a Rectangular Array in ClassGradeBook
Figure 8.20 contains a version of classGradeBookthat uses a rectangular arraygradesto 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 the grades for the whole class on one of the exams the students took during the course. An app such asGrade-
BookTest(Fig. 8.21) passes the array as an argument to theGradeBookconstructor. In this example, we use a 10-by-3 array containing 10 students’ grades on three exams. Five meth- ods perform array manipulations to process the grades. Each method is similar to its coun- terpart in the earlier one-dimensional-array version of classGradeBook(Fig. 8.15). Method
GetMinimum(lines 44–58 in Fig. 8.20) determines the lowest grade of any student for the se- mester. MethodGetMaximum(lines 61–75) determines the highest grade of any student for the semester. MethodGetAverage(lines 78–90) determines a particular student’s semester average. MethodOutputBarChart(lines 93–122) outputs a bar chart of the distribution of all student grades for the semester. MethodOutputGrades(lines 125–149) outputs the two- dimensional array in tabular format, along with each student’s semester average.
1 // Fig. 8.20: GradeBook.cs
2 // Grade book using a rectangular array to store grades.
3 using System;
4
5 public class GradeBook 6 {
7 8
9 // auto-implemented property CourseName 10 public string CourseName { get; set; } 11
12 // two-parameter constructor initializes
13 // auto-implemented property CourseName and grades array 14 public GradeBook( string name, int[ , ] gradesArray )
15 {
16 CourseName = name; // set CourseName to name 17
18 } // end two-parameter GradeBook constructor 19
20 // display a welcome message to the GradeBook user 21 public void DisplayMessage()
22 {
23 // auto-implemented property CourseName gets the name of course 24 Console.WriteLine( "Welcome to the grade book for\n{0}!\n",
25 CourseName );
26 } // end method DisplayMessage 27
28 // perform various operations on the data 29 public void ProcessGrades()
30 {
Fig. 8.20 | Grade book using a rectangular array to store grades. (Part 1 of 4.)
private int[ , ] grades; // rectangular array of student grades
grades = gradesArray; // initialize grades array
8.11 Case Study:GradeBookUsing a Rectangular Array 323
31 // output grades array 32 OutputGrades();
33
34 // call methods GetMinimum and GetMaximum 35 Console.WriteLine( "\n{0} {1}\n{2} {3}\n",
36 "Lowest grade in the grade book is", GetMinimum(), 37 "Highest grade in the grade book is", GetMaximum() );
38
39 // output grade distribution chart of all grades on all tests 40 OutputBarChart();
41 } // end method ProcessGrades 42
43 // find minimum grade 44 public int GetMinimum()
45 {
46 // assume first element of grades array is smallest 47 int lowGrade = grades[ 0, 0 ];
48 49 50 51 52 53 54 55 56
57 return lowGrade; // return lowest grade 58 } // end method GetMinimum
59
60 // find maximum grade 61 public int GetMaximum()
62 {
63 // assume first element of grades array is largest 64 int highGrade = grades[ 0, 0 ];
65
66 // loop through elements of rectangular grades array 67 foreach ( int grade in grades )
68 {
69 // if grade greater than highGrade, assign it to highGrade 70 if ( grade > highGrade )
71 highGrade = grade;
72 } // end foreach 73
74 return highGrade; // return highest grade 75 } // end method GetMaximum
76 77 78 79 80 81 82 83
Fig. 8.20 | Grade book using a rectangular array to store grades. (Part 2 of 4.)
// loop through elements of rectangular grades array foreach ( int grade in grades )
{
// if grade less than lowGrade, assign it to lowGrade if ( grade < lowGrade )
lowGrade = grade;
} // end foreach
// determine average grade for particular student public double GetAverage( int student )
{
// get the number of grades per student int amount = grades.GetLength( 1 );
int total = 0; // initialize total
84 85 86 87 88 89 90 91
92 // output bar chart displaying overall grade distribution 93 public void OutputBarChart()
94 {
95 Console.WriteLine( "Overall grade distribution:" );
96
97 // stores frequency of grades in each range of 10 grades 98 int[] frequency = new int[ 11 ];
99 100 101 102 103 104 105
106 // for each grade frequency, display bar in chart 107 for ( int count = 0; count < frequency.Length; ++count )
108 {
109 // output bar label ( "00-09: ", ..., "90-99: ", "100: " ) 110 if ( count == 10 )
111 Console.Write( " 100: " );
112 else
113 Console.Write( "{0:D2}-{1:D2}: ", 114 count * 10, count * 10 + 9 );
115
116 // display bar of asterisks
117 for ( int stars = 0; stars < frequency[ count ]; ++stars ) 118 Console.Write( "*" );
119
120 Console.WriteLine(); // start a new line of output 121 } // end outer for
122 } // end method OutputBarChart 123
124 // output the contents of the grades array 125 public void OutputGrades()
126 {
127 Console.WriteLine( "The grades are:\n" );
128 Console.Write( " " ); // align column heads 129
130 // create a column heading for each of the tests
131 for ( int test = 0; test < grades.GetLength( 1 ); ++test ) 132 Console.Write( "Test {0} ", test + 1 );
133
134 Console.WriteLine( "Average" ); // student average column heading 135
Fig. 8.20 | Grade book using a rectangular array to store grades. (Part 3 of 4.)
// sum grades for one student
for ( int exam = 0; exam < amount; ++exam ) total += grades[ student, exam ];
// return average of grades return ( double ) total / amount;
} // end method GetAverage
// for each grade in GradeBook, increment the appropriate frequency foreach ( int grade in grades )
{
++frequency[ grade / 10 ];
} // end foreach
8.11 Case Study:GradeBookUsing a Rectangular Array 325
Processing a Two-Dimensional Array with aforeachStatement
MethodsGetMinimum,GetMaximumandOutputBarCharteach loop through array grades using theforeachstatement—for example, theforeachstatement from methodGetMin-
imum (lines 50–55). To find the lowest overall grade, this foreach statement iterates through rectangular arraygradesand compares each element to variablelowGrade. If a grade is less thanlowGrade,lowGradeis set to that grade.
When theforeachstatement traverses the elements of arraygrades, it looks at each element of the first row in order by index, then each element of the second row in order by index and so on. Theforeachstatement in lines 50–55 traverses the elements ofgrade in the same order as the following equivalent code, expressed with nestedforstatements:
When theforeachstatement completes,lowGradecontains the lowest grade in the rect- angular array. MethodGetMaximumworks similarly to methodGetMinimum.
MethodOutputBarChart
MethodOutputBarChart(lines 93–122) displays the grade distribution as a bar chart. The syntax of theforeachstatement (lines 101–104) is identical for one-dimensional and two- dimensional arrays.
MethodOutputGrades
MethodOutputGrades(lines 125–149) uses nestedforstatements to output values of the arraygrades, in addition to each student’s semester average. The output in Fig. 8.21 shows the result, which resembles the tabular format of an instructor’s physical grade book. Lines 131–132 (in Fig. 8.20) display the column headings for each test. We use theforstatement rather than theforeachstatement here so that we can identify each test with a number.
Similarly, theforstatement in lines 137–148 first outputs a row label using a counter vari- 136 // create rows/columns of text representing array grades
137 for ( int student = 0; student < grades.GetLength( 0 ); ++student )
138 {
139 Console.Write( "Student {0,2}", student + 1 );
140
141 // output student's grades
142 for ( int grade = 0; grade < grades.GetLength( 1 ); ++grade ) 143 Console.Write( "{0,8}", grades[ student, grade ] );
144
145 // call method GetAverage to calculate student's average grade;
146 // pass row number as the argument to GetAverage 147 Console.WriteLine( "{0,9:F}", );
148 } // end outer for
149 } // end method OutputGrades 150 } // end class GradeBook
for ( int row = 0; row < grades.GetLength( 0 ); ++row )
for ( int column = 0; column < grades.GetLength( 1 ); ++column ) {
if ( grades[ row, column ] < lowGrade ) lowGrade = grades[ row, column ];
}
Fig. 8.20 | Grade book using a rectangular array to store grades. (Part 4 of 4.)
GetAverage( student )
able to identify each student (line 139). Although array indices start at 0, lines 132 and 139 outputtest + 1andstudent + 1, respectively, to produce test and student numbers start- ing at1(see Fig. 8.21). The innerforstatement in lines 142–143 uses the outerforstate- ment’s counter variablestudentto loop through a specific row of arraygradesand output each student’s test grade. Finally, line 147 obtains each student’s semester average by pass- ing the row index ofgrades(i.e.,student) to methodGetAverage.
MethodGetAverage
MethodGetAverage(lines 78–90) takes one argument—the row index for a particular student. When line 147 callsGetAverage, the argument isintvaluestudent, which spec- ifies the particular row of rectangular arraygrades. Method GetAverage calculates the sum of the array elements on this row, divides the total by the number of test results and returns the floating-point result as adoublevalue (line 89).
ClassGradeBookTestThat Demonstrates ClassGradeBook
The app in Fig. 8.21 creates an object of classGradeBook(Fig. 8.20) using the two-dimen- sional array ofints thatgradesArrayreferences (Fig. 8.21, lines 9–18). Lines 20–21 pass a course name andgradesArrayto theGradeBookconstructor. Lines 22–23 then invoke
myGradeBook’sDisplayMessageandProcessGradesmethods to display a welcome mes- sage and obtain a report summarizing the students’ grades for the semester, respectively.
1 // Fig. 8.21: GradeBookTest.cs
2 // Create a GradeBook object using a rectangular array of grades.
3 public class GradeBookTest 4 {
5 // Main method begins app execution 6 public static void Main( string[] args )
7 {
8 9 10 11 12 13 14 15 16 17 18 19
20 GradeBook myGradeBook = new GradeBook(
21 "CS101 Introduction to C# Programming", gradesArray );
22 myGradeBook.DisplayMessage();
23 myGradeBook.ProcessGrades();
24 } // end Main
25 } // end class GradeBookTest Welcome to the grade book for
CS101 Introduction to C# Programming!
Fig. 8.21 | Create aGradeBookobject using a rectangular array of grades. (Part 1 of 2.)
// rectangular array of student grades int[ , ] gradesArray = { { 87, 96, 70 },
{ 68, 87, 90 }, { 94, 100, 90 }, { 100, 81, 82 }, { 83, 65, 85 }, { 78, 87, 65 }, { 85, 75, 83 }, { 91, 94, 100 }, { 76, 72, 84 }, { 87, 93, 73 } };