In Section 8.9, we presented class GradeBook (Fig. 8.15), which used a one-dimensional array to store student grades on a single exam. In most courses, students take several exams. 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 Class GradeBook
Figure 8.20 contains a version of class GradeBook that uses a rectangular 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 the grades for the whole class on one of the exams the students took during the course. An application such as GradeBookTest (Fig. 8.21) passes the array as an argument to the GradeBook constructor. In this example, we use a 10-by-3 array containing 10 students' grades on three exams. Five methods perform 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.15). Method GetMinimum (lines 5468) determines the lowest grade of any student for the semester. Method GetMaximum (lines 7185) determines the highest grade of any student for the semester. Method GetAverage (lines 88100) determines a particular student's semester average. Method OutputBarChart (lines 103132) outputs a bar chart of the distribution of all student grades for the semester. Method OutputGrades (lines 135159) outputs the two-dimensional array in tabular format, along with each student's semester average.
Figure 8.20. Grade book using rectangular array to store grades.
1 // Fig. 8.20: GradeBook.cs 2 // Grade book using rectangular array to store grades. 3 using System; 4 5 public class GradeBook 6 { 7 private string courseName; // name of course this grade book represents 8 private int[ , ] grades; // rectangular array of student grades 9 10 // two-parameter constructor initializes courseName and grades array 11 public GradeBook( string name, int[ , ] gradesArray ) 12 { 13 CourseName = name; // initialize courseName 14 grades = gradesArray; // initialize grades array 15 } // end two-parameter GradeBook constructor 16 17 // property that gets and sets the course name 18 public string CourseName 19 { 20 get 21 { 22 return courseName; 23 } // end get 24 set 25 { 26 courseName = value; 27 } // end set 28 } // end property CourseName 29 30 // display a welcome message to the GradeBook user 31 public void DisplayMessage() 32 {33 // CourseName property gets the name of the course 34 Console.WriteLine( "Welcome to the grade book for {0}! ", 35 CourseName ); 36 } // end method DisplayMessage 37 38 // perform various operations on the data 39 public void ProcessGrades() 40 { 41 // output grades array 42 OutputGrades(); 43 44 // call methods GetMinimum and GetMaximum 45 Console.WriteLine( " {0} {1} {2} {3} ", 46 "Lowest grade in the grade book is", GetMinimum(), 47 "Highest grade in the grade book is", GetMaximum() ); 48 49 // output grade distribution chart of all grades on all tests 50 OutputBarChart(); 51 } // end method ProcessGrades 52 53 // find minimum grade 54 public int GetMinimum() 55 { 56 // assume first element of grades array is smallest 57 int lowGrade = grades[ 0, 0 ]; 58 59 // loop through elements of rectangular grades array 60 foreach ( int grade in grades ) 61 { 62 // if grade less than lowGrade, assign it to lowGrade 63 if ( grade < lowGrade ) 64 lowGrade = grade; 65 } // end foreach 66 67 return lowGrade; // return lowest grade 68 } // end method GetMinimum 69 70 // find maximum grade 71 public int GetMaximum() 72 { 73 // assume first element of grades array is largest 74 int highGrade = grades[ 0, 0 ]; 75 76 // loop through elements of rectangular grades array 77 foreach ( int grade in grades ) 78 { 79 // if grade greater than highGrade, assign it to highGrade 80 if ( grade > highGrade ) 81 highGrade = grade; 82 } // end foreach 83 84 return highGrade; // return highest grade 85 } // end method GetMaximum 86 87 // determine average grade for particular student 88 public double GetAverage( int student ) 89 { 90 // get the number of grades per student 91 int amount = grades.GetLength( 1 ); 92 int total = 0; // initialize total 93 94 // sum grades for one student 95 for ( int exam = 0; exam < amount; exam++ ) 96 total += grades[ student, exam ]; 97 98 // return average of grades 99 return ( double ) total / amount; 100 } // end method GetAverage 101 102 // output bar chart displaying overall grade distribution 103 public void OutputBarChart() 104 { 105 Console.WriteLine( "Overall grade distribution:" ); 106 107 // stores frequency of grades in each range of 10 grades 108 int[] frequency = new int[ 11 ]; 109 110 // for each grade in GradeBook, increment the appropriate frequency 111 foreach ( int grade in grades ) 112 { 113 ++frequency[ grade / 10 ]; 114 } // end foreach 115 116 // for each grade frequency, print bar in chart 117 for ( int count = 0; count < frequency.Length; count++ ) 118 { 119 // output bar label ( "00-09: ", ..., "90-99: ", "100: " ) 120 if ( count == 10 ) 121 Console.Write( " 100: " ); 122 else 123 Console.Write( "{0:D2}-{1:D2}: ", 124 count * 10, count * 10 + 9 ); 125 126 // print bar of asterisks 127 for ( int stars = 0; stars < frequency[ count ]; stars++ ) 128 Console.Write( "*" ); 129 130 Console.WriteLine(); // start a new line of output 131 } // end outer for 132 } // end method OutputBarChart 133 134 // output the contents of the grades array 135 public void OutputGrades() 136 { 137 Console.WriteLine( "The grades are: " ); 138 Console.Write( " " ); // align column heads 139 140 // create a column heading for each of the tests 141 for ( int test = 0; test < grades.GetLength( 1 ); test++ ) 142 Console.Write( "Test {0} ", test + 1 ); 143 144 Console.WriteLine( "Average" ); // student average column heading 145 146 // create rows/columns of text representing array grades 147 for ( int student = 0; student < grades.GetLength( 0 ); student++ ) 148 { 149 Console.Write( "Student {0,2}", student + 1 ); 150 151 // output student's grades 152 for ( int grade = 0; grade < grades.GetLength( 1 ); grade++ ) 153 Console.Write( "{0,8}", grades[ student, grade ] ); 154 155 // call method GetAverage to calculate student's average grade; 156 // pass row number as the argument to GetAverage 157 Console.WriteLine( "{0,9:F2}",GetAverage( student ) ); 158 } // end outer for 159 } // end method OutputGrades 160 } // end class GradeBook |
Methods GetMinimum, GetMaximum and OutputBarChart each loop through array grades using the foreach statementfor example, the foreach statement from method GetMinimum (lines 6065). To find the lowest overall grade, this foreach statement iterates through rectangular array grades and compares each element to variable lowGrade. If a grade is less than lowGrade, lowGrade is set to that grade.
When the foreach statement traverses the elements of the grades array, 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. The foreach statement in lines 6065 traverses the elements of grade in the same order as the following equivalent code, expressed with nested for statements:
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 ]; }
When the foreach statement completes, lowGrade contains the lowest grade in the rectangular array. Method GetMaximum works similarly to method GetMinimum.
Method OutputBarChart in Fig. 8.20 displays the grade distribution as a bar chart. Note that the syntax of the foreach statement (lines 111114) is identical for one-dimensional and two-dimensional arrays.
Method OutputGrades (lines 135159) uses nested for statements to output values of the array grades, 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 141142 print the column headings for each test. We use the for statement rather than the foreach statement here so that we can identify each test with a number. Similarly, the for statement in lines 147158 first outputs a row label using a counter variable to identify each student (line 149). Although array indices start at 0, note that lines 142 and 149 output test + 1 and student + 1, respectively, to produce test and student numbers starting at 1 (see Fig. 8.21). The inner for statement in lines 152153 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 row index of grades (i.e., student) to method GetAverage.
Figure 8.21. Create GradeBook object using a rectangular array of grades.
1 // Fig. 8.21: GradeBookTest.cs 2 // Create GradeBook object using a rectangular array of grades. 3 public class GradeBookTest 4 { 5 // Main method begins application execution 6 public static void Main( string[] args ) 7 { 8 // rectangular array of student grades 9 int[ , ] gradesArray = { { 87, 96, 70 }, 10 { 68, 87, 90 }, 11 { 94, 100, 90 }, 12 { 100, 81, 82 }, 13 { 83, 65, 85 }, 14 { 78, 87, 65 }, 15 { 85, 75, 83 }, 16 { 91, 94, 100 }, 17 { 76, 72, 84 }, 18 { 87, 93, 73 } }; 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
|
Method GetAverage (lines 88100) takes one argumentthe row index for a particular student. When line 157 calls GetAverage, the argument is int value student, which specifies the particular row of rectangular array grades. 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 a double value (line 99).
Class GradeBookTest That Demonstrates Class GradeBook
The application in Fig. 8.21 creates an object of class GradeBook (Fig. 8.20) using the two-dimensional array of ints named gradesArray (declared and initialized in lines 918). Lines 2021 pass a course name and gradesArray to the GradeBook constructor. Lines 2223 then invoke myGradeBook's DisplayMessage and ProcessGrades methods to display a welcome message and obtain a report summarizing the students' grades for the semester, respectively.
Preface
Index
Introduction to Computers, the Internet and Visual C#
Introduction to the Visual C# 2005 Express Edition IDE
Introduction to C# Applications
Introduction to Classes and Objects
Control Statements: Part 1
Control Statements: Part 2
Methods: A Deeper Look
Arrays
Classes and Objects: A Deeper Look
Object-Oriented Programming: Inheritance
Polymorphism, Interfaces & Operator Overloading
Exception Handling
Graphical User Interface Concepts: Part 1
Graphical User Interface Concepts: Part 2
Multithreading
Strings, Characters and Regular Expressions
Graphics and Multimedia
Files and Streams
Extensible Markup Language (XML)
Database, SQL and ADO.NET
ASP.NET 2.0, Web Forms and Web Controls
Web Services
Networking: Streams-Based Sockets and Datagrams
Searching and Sorting
Data Structures
Generics
Collections
Appendix A. Operator Precedence Chart
Appendix B. Number Systems
Appendix C. Using the Visual Studio 2005 Debugger
Appendix D. ASCII Character Set
Appendix E. Unicode®
Appendix F. Introduction to XHTML: Part 1
Appendix G. Introduction to XHTML: Part 2
Appendix H. HTML/XHTML Special Characters
Appendix I. HTML/XHTML Colors
Appendix J. ATM Case Study Code
Appendix K. UML 2: Additional Diagram Types
Appendix L. Simple Types
Index