8.10 Case Study: GradeBook Using a Rectangular Array

In Section 8.8, 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 shows the output that summarizes 10 students’ grades on three exams. Figure 8.21 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 app such as GradeBookTest (Fig. 8.22) 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.

Fig. 8.20 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:
00-09:
10-19:
20-29:
30-39:
40-49:
50-59:
60-69: ***
70-79: ******
80-89: ***********
90-99: *******
 100: ***

Fig. 8.21 Grade book using a rectangular array to store grades.

Alternate View

  1   // Fig. 8.21: GradeBook.cs
  2   // Grade book using a rectangular array to store grades.
  3   using System;
  4
  5   class GradeBook
  6   {
  7      private int[,] grades; // rectangular array of student grades
  8
  9      // auto-implemented property CourseName
 10      public string CourseName { get; }
 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         grades = gradesArray; // initialize grades array
 18      }
 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(
 25            $"Welcome to the grade book for
{CourseName}!
");
 26      }
 27
 28      // perform various operations on the data
 29      public void ProcessGrades()
 30      {
 31         // output grades array
 32         OutputGrades();
 33
 34         // call methods GetMinimum and GetMaximum
 35         Console.WriteLine(
 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      }
 42
 43      // find minimum grade
 44      public int GetMinimum()
 45      {
 46         // assume first element of grades array is smallest
 47         var lowGrade = grades[0, 0];
 48
 49         // loop through elements of rectangular grades array    
 50         foreach (var grade in grades)                           
 51         {                                                       
 52            // if grade less than lowGrade, assign it to lowGrade
 53            if (grade < lowGrade)                                
 54            {                                                    
 55               lowGrade = grade;                                 
 56            }                                                    
 57         }                                                       
 58
 59         return lowGrade; // return lowest grade
 60      }
 61
 62      // find maximum grade
 63      public int GetMaximum()
 64      {
 65         // assume first element of grades array is largest
 66         var highGrade = grades[0, 0];
 67
 68         // loop through elements of rectangular grades array
 69         foreach (var grade in grades)
 70         {
 71            // if grade greater than highGrade, assign it to highGrade
 72            if (grade > highGrade)
 73            {
 74               highGrade = grade;
 75            }
 76         }
 77
 78         return highGrade; // return highest grade
 79      }
 80
 81      // determine average grade for particular student
 82      public double GetAverage(int student)            
 83      {                                                
 84         // get the number of grades per student       
 85         var gradeCount = grades.GetLength(1);         
 86         var total = 0.0; // initialize total          
 87                                                       
 88         // sum grades for one student                 
 89         for (var exam = 0; exam < gradeCount; ++exam) 
 90         {                                             
 91            total += grades[student, exam];            
 92         {                                             
 93                                                       
 94         // return average of grades                   
 95         return total / gradeCount;                    
 96      }                                                
 97
 98      // output bar chart displaying overall grade distribution
 99      public void OutputBarChart()
100      {
101         Console.WriteLine("Overall grade distribution:");
102
103         // stores frequency of grades in each range of 10 grades
104         var frequency = new int[11];
105
106         // for each grade in GradeBook, increment the appropriate frequency
107         foreach (var grade in grades)
108         {
109            ++frequency[grade / 10];
110         }                        
111
112         // for each grade frequency, display bar in chart
113         for (var count = 0; count < frequency.Length; ++count)
114         {
115            // output bar label ("00-09: ", ..., "90-99: ", "100: ")
116            if (count == 10)
117            {
118               Console.Write(" 100: ");
119            }
120            else
121            {
122               Console.Write($"{count * 10:D2}-{count * 10 + 9:D2}: ");
123            }
124
125            // display bar of asterisks
126            for (var stars = 0; stars < frequency[count]; ++stars)
127            {
128               Console.Write("*");
129            }
130
131            Console.WriteLine(); // start a new line of output
132         }
133      }
134
135      // output the contents of the grades array
136      public void OutputGrades()
137      {
138         Console.WriteLine("The grades are:
");
139         Console.Write("             "); // align column heads
140
141         // create a column heading for each of the tests
142         for (var test = 0; test < grades.GetLength(1); ++test)
143         {
144            Console.Write($"Test {test + 1} ");
145         }
146
147         Console.WriteLine("Average"); // student average column heading
148
149         // create rows/columns of text representing array grades
150         for (var student = 0; student < grades.GetLength(0); ++student)
151         {
152            Console.Write($"Student {student + 1,2}");
153
154            // output student's grades
155            for (var grade = 0; grade < grades.GetLength(1); ++grade)
156            {
157               Console.Write($"{grades[student, grade],8}");
158            }
159
160            // call method GetAverage to calculate student's average grade;
161            // pass row number as the argument to GetAverage
162            Console.WriteLine($"{GetAverage(student),9:F}");
163         }
164      }
165   }

Five methods perform array manipulations to process the grades. Each method is similar to its counterpart in the one-dimensional-array GradeBook (Fig. 8.15). Method Get-Minimum (lines 44–60 in Fig. 8.21) determines the lowest grade of any student. Method GetMaximum (lines 63–79) determines the highest grade of any student. Method Get-Average (lines 82–96) determines a particular student’s semester average. Method OutputBarChart (lines 99–133) outputs a bar chart of the distribution of all student grades for the semester. Method OutputGrades (lines 136–164) outputs the two-dimensional array in tabular format, along with each student’s semester average.

Processing a Two-Dimensional Array with a foreach Statement

Methods GetMinimum, GetMaximum and OutputBarChart each loop through array grades using the foreach statement—for example, the foreach statement from method GetMinimum (lines 50–57). 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 array grades, 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 (lines 50–57) traverses the elements of grades in the same order as the following equivalent code, expressed with nested for statements:


for (var row = 0; row < grades.GetLength(0); ++row)
{
   for (var 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. Note the simplicity of using foreach vs. the preceding nested for statement.

Software Engineering Observation 8.2

“Keep it simple” is good advice for most of the code you’ll write.

Method OutputBarChart

Method OutputBarChart (lines 99–133) displays the grade distribution as a bar chart. The syntax of the foreach statement (lines 107–110) is identical for one-dimensional and two-dimensional arrays.

Method OutputGrades

Method OutputGrades (lines 136–164) uses nested for statements to output grades’ values, in addition to each student’s semester average. The output in Fig. 8.20 shows the result, which resembles the tabular format of an instructor’s physical grade book. Lines 142– 145 (in Fig. 8.21) display 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 150–163 first outputs a row label using a counter variable to identify each student (line 152). Although array indices start at 0, lines 144 and 152 output test + 1 and student + 1, respectively, to produce test and student numbers starting at 1 (see Fig. 8.20). The inner for statement in lines 155–158 of Fig. 8.21 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 162 obtains each student’s semester average by passing the row index of grades (i.e., student) to method GetAverage.

Method GetAverage

Method GetAverage (lines 82–96) takes one argument—the row index for a particular student. When line 162 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 95).

Class GradeBookTest That Demonstrates Class GradeBook

Figure 8.22 creates an object of class GradeBook (Fig. 8.21) using the two-dimensional array of ints that gradesArray references (Fig. 8.22, lines 9–18). Lines 20–21 pass a course name and gradesArray to the GradeBook constructor. Lines 22–23 then invoke myGrade-Book’s DisplayMessage and ProcessGrades methods to display a welcome message and obtain a report summarizing the students’ grades for the semester, respectively.

Fig. 8.22 Create a GradeBook object using a rectangular array of grades.

Alternate View

  1   // Fig. 8.22: GradeBookTest.cs
  2   // Create a GradeBook object using a rectangular array of grades.
  3   class GradeBookTest
  4   {
  5      // Main method begins app execution
  6      static void Main()
  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      }
 25   }
..................Content has been hidden....................

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