8.4 Examples Using Arrays

This section presents several examples that demonstrate declaring arrays, creating arrays, initializing arrays and manipulating array elements.

8.4.1 Creating and Initializing an Array

In Fig. 8.2, line 10 of uses an array-creation expression to create a five-element int array with values initialized to 0 by default. The resulting array’s reference initializes the variable array to refer to the new array object.

Fig. 8.2 Creating an array.

Alternate View

  1   // Fig. 8.2: InitArray.cs
  2   // Creating an array.
  3   using System;
  4
  5   class InitArray
  6   {
  7      static void Main()
  8      {
  9      // create the space for array and initialize to default zeros
 10      int[] array = new int[5]; // array contains 5 int elements
 11
 12      Console.WriteLine($"{"Index"}{"Value",8}"); // headings
 13
 14       // output each array element's value
 15       for (int counter = 0; counter < array.Length; ++counter)
 16       {                                                       
 17          Console.WriteLine($"{counter,5}{array[counter],8}"); 
 18       {                                                       
 19    }
 20 }

Index Value
    0     0
    1     0
    2     0
    3     0
    4     0

Line 12 displays column headings for the app’s output. The first column will display each array element’s index (04 for a five-element array), and the second column contains each element’s default value (0). The column head "Value" is right-aligned in a field width of 8, as specified in the string-interpolation expression


{"Value",8}

The for statement (lines 15–18) displays each array element’s index (represented by counter) and value (represented by array[counter]). The loop-control variable counter is initially 0—index values start at 0, so zero-based counting allows the loop to access every element. The loop-continuation condition uses the property array.Length (line 15) to obtain array’s length. In this example, the length is 5, so the loop continues executing as long as counter’s value is less than 5. The highest index in a five-element array is 4, so using the less-than operator in the loop-continuation condition guarantees that the loop does not attempt to access an element beyond the end of the array (i.e., during the final iteration of the loop, counter is 4). We’ll soon see what happens when an out-of-range index is encountered at execution time.

8.4.2 Using an Array Initializer

An app can create an array and initialize its elements with an array initializer—a comma-separated list of expressions (called an initializer list) enclosed in braces. The array length is determined by the number of elements in the initializer list. For example, the declaration


int[] n = {10, 20, 30, 40, 50};

creates a five-element array with index values 0, 1, 2, 3 and 4. Element n[0] is initialized to 10, n[1] is initialized to 20 and so on. This statement does not require new to create the array object—the compiler counts the number of initializers (5) to determine the array’s size, then sets up the appropriate new operation “behind the scenes.” The app in Fig. 8.3 initializes an integer array with 5 values (line 10) and displays the array in tabular format. Lines 15–18 for displaying the array’s contents are identical to lines 15–18 of Fig. 8.2.

Fig. 8.3 Initializing the elements of an array with an array initializer.

Alternate View

  1   // Fig. 8.3: InitArray.cs
  2   // Initializing the elements of an array with an array initializer.
  3   using System;
  4
  5   class InitArray
  6   {
  7      static void Main()
  8      {
  9         // initializer list specifies the value of each element
 10         int[] array = {32, 27, 64, 18, 95};
 11
 12         Console.WriteLine($"{"Index"}{"Value",8}"); // headings
 13
 14         // output each array element's value
 15         for (int counter = 0; counter < array.Length; ++counter)
 16         {
 17            Console.WriteLine($"{counter,5}{array[counter],8}");
 18         }
 19      }
 20   }

Index Value
    0    32
    1    27
    2    64
    3    18
    4    95

8.4.3 Calculating a Value to Store in Each Array Element

Figure 8.4 creates a 5-element array and assigns to its elements the even integers from 2 to 10 (2, 4, 6, 8 and 10). Then the app displays the array in tabular format. Lines 13–16 calculate an array element’s value by multiplying the current value of the for loop’s control variable counter by 2, then adding 2.

Fig. 8.4 Calculating values to be placed into the elements of an array.

Alternate View

  1   // Fig. 8.4: InitArray.cs
  2   // Calculating values to be placed into the elements of an array.
  3   using System;
  4
  5   class InitArray
  6   {
  7      static void Main()
  8      {
  9         const int ArrayLength = 5; // create a named constant   
 10         int[] array = new int[ArrayLength]; // create array     
 11
 12         // calculate value for each array element
 13         for (int counter = 0; counter < array.Length; ++counter)
 14         {
 15            array[counter] = 2 + 2 * counter;   
 16         }
 17
 18         Console.WriteLine($"{"Index"}{"Value",8}"); // headings
 19
 20         // output each array element's value
 21         for (int counter = 0; counter < array.Length; ++counter)
 22         {
 23            Console.WriteLine($"{counter,5}{array[counter],8}");
 24         }
 25      }
 26   }

Index Value
    0     2
    1     4
    2     6
    3     8
    4    10

Declaring a Named Constant with const

Line 9 uses the modifier const to declare the constant ArrayLength, which is initialized to 5. Constants must be initialized in their declarations and cannot be modified thereafter. Constants use the same Pascal Case naming conventions as classes, methods and properties.

Good Programming Practice 8.1

Constants are also called named constants. Apps using constants often are more readable than those that use literal values (e.g., 5)—a named constant such as ArrayLength clearly indicates its purpose, whereas the literal value 5 could have different meanings based on the context in which it’s used. Another advantage to using named constants is that if the constant’s value must be changed, the change is necessary only in the declaration, thus reducing code-maintenance costs.

 

Good Programming Practice 8.2

Defining the size of an array as a named constant instead of a literal makes code clearer. This technique eliminates so-called magic numbers. For example, repeatedly mentioning the size 5 in array-processing code for a five-element array gives the number 5 an artificial significance and can be confusing when the program includes other 5s that have nothing to do with the array size.

 

Common Programming Error 8.2

Assigning a value to a named constant after it’s been initialized is a compilation error.

 

Common Programming Error 8.3

Attempting to declare a named constant without initializing it is a compilation error.

8.4.4 Summing the Elements of an Array

Often, the elements of an array represent a series of values to be used in a calculation. For example, if the elements of an array represent exam grades, an instructor may wish to sum the elements then use the sum to calculate the class average. The GradeBook examples later in the chapter (Sections 8.8 and 8.10) use this technique. Figure 8.5 sums the values contained in a 10-element int array, which is declared and initialized in line 9. The for statement performs the calculations by adding each element’s value to the total (line 15).3

Fig. 8.5 Computing the sum of the elements of an array.

Alternate View

  1   // Fig. 8.5: SumArray.cs
  2   // Computing the sum of the elements of an array.
  3   using System;
  4
  5   class SumArray
  6   {
  7      static void Main()
  8      {
  9         int[] array = {87, 68, 94, 100, 83, 78, 85, 91, 76, 87};
 10         int total = 0;
 11
 12         // add each element's value to total
 13         for (int counter = 0; counter < array.Length; ++counter)
 14         {
 15            total += array[counter]; // add element value to total
 16         }
 17
 18         Console.WriteLine($"Total of array elements: {total}");
 19      }
 20   }

Total of array elements: 849

8.4.5 Iterating Through Arrays with foreach

So far, we’ve used counter-controlled for statements to iterate through array elements. In this section, we introduce the foreach statement, which iterates through an entire array’s elements (or the elements of a collection, as you’ll see in Section 9.4). The syntax of a foreach statement is


foreach (type identifier in arrayName)
{
   statement
}

where type and identifier are the type and name (e.g., int number) of the iteration variable, and arrayName is the array through which to iterate. The iteration variable’s type must be consistent with the array’s element type. The iteration variable represents successive values in the array on successive iterations of the foreach statement.

Figure 8.6 uses the foreach statement (lines 13–16) to calculate the sum of array’s elements. The iteration variable number’s type is declared as int (line 13), because array contains int values. The foreach statement iterates through successive int values in array one by one, starting with the first element. The foreach header can be read concisely as “for each iteration, assign array’s next element to int variable number, then execute the following statement.” Lines 13–16 are equivalent to the counter-controlled iteration used in lines 13–16 of Fig. 8.5.

Common Programming Error 8.4

Any attempt to change the iteration variable’s value in the body of a foreach statement results in a compilation error.

Fig. 8.6 Using the foreach statement to total integers in an array.

Alternate View

  1   // Fig. 8.6: ForEachTest.cs
  2   // Using the foreach statement to total integers in an array.
  3   using System;
  4
  5   class ForEachTest
  6   {
  7      static void Main()
  8      {
  9         int[] array = {87, 68, 94, 100, 83, 78, 85, 91, 76, 87};
 10         int total = 0;
 11
 12         // add each element's value to total
 13         foreach (int number in array)
 14         {
 15            total += number;
 16         }
 17
 18         Console.WriteLine($"Total of array elements: {total}");
 19      }
 20   }

Total of array elements: 849

foreach vs. for

The foreach statement can be used in place of the for statement whenever code looping through an array does not require access to the current array element’s index. For example, totaling the integers in an array requires access only to the element values—each element’s index is irrelevant. If an app must use a counter for some reason other than simply to loop through an array (e.g., to calculate an element’s value based on the counter’s value, as in Fig. 8.4), you should use the for statement.

Common Programming Error 8.5

Attempting to modify an array element’s value using a foreach statement’s iteration variable is a logic error—the iteration variable can be used only to access each array element’s value, not modify it.

8.4.6 Using Bar Charts to Display Array Data Graphically; Introducing Type Inference with var

Many apps present data to users in a graphical manner. For example, numeric values are often displayed as bars in a bar chart. In such a chart, longer bars represent proportionally larger numeric values. One simple way to display numeric data graphically is with a bar chart that shows each numeric value as a bar of asterisks (*).

An instructor might graph the number of grades in each of several categories to visualize the grade distribution for an exam. Suppose the grades on an exam were 87, 68, 94, 100, 83, 78, 85, 91, 76 and 87. Included were one grade of 100, two grades in the 90s, four grades in the 80s, two grades in the 70s, one grade in the 60s and no grades below 60. Our next app (Fig. 8.7) stores this grade-distribution data in an array of 11 elements, each corresponding to a category of grades. For example, array[0] indicates the number of grades in the range 0–9, array[7] the number of grades in the range 70–79 and array[10] the number of 100 grades. The two versions of class GradeBook in Sections 8.8 and 8.10 contain code that calculates these grade frequencies based on a set of grades. For now, we manually create array and initialize it with the number of grades in each range (Fig. 8.7, line 9). We discuss the keyword var (lines 14 and 27) after we present the app’s logic.

Fig. 8.7 Bar chart displaying app.

Alternate View

  1   // Fig. 8.7: BarChart.cs
  2   // Bar chart displaying app.
  3   using System;
  4
  5   class BarChart
  6   {
  7      static void Main()
  8      {
  9         int[] array = {0, 0, 0, 0, 0, 0, 1, 2, 4, 2, 1}; // distribution
 10
 11         Console.WriteLine("Grade distribution:");
 12
 13         // for each array element, output a bar of the chart
 14         for (var counter = 0; counter < array.Length; ++counter)
 15         {
 16            // output bar labels ("00-09: ", ..., "90-99: ", "100: ")
 17            if (counter == 10)
 18            {
 19               Console.Write(" 100: ");
 20            }
 21            else
 22            {
 23               Console.Write($"{counter * 10:D2}-{counter * 10 + 9:D2}: ");
 24            }
 25
 26            // display bar of asterisks
 27            for (var stars = 0; stars < array[counter]; ++stars)
 28            {
 29               Console.Write("*");
 30            }
 31
 32            Console.WriteLine(); // start a new line of output
 33         }
 34      }
 35   }

Grade distribution:
00-09:
10-19:
20-29:
30-39:
40-49:
50-59:
60-69: *
70-79: **
80-89: ****
90-99: **
  100: *

The app reads the numbers from the array and graphs the information as a bar chart. Each grade range is followed by a bar of asterisks indicating the number of grades in that range. To label each bar, lines 17–24 display a grade range (e.g., "70-79: ") based on the current value of counter. When counter is 10, line 19 displays " 100: " to align the colon with the other bar labels. When counter is not 10, line 23 uses the string-interpolation expressions


{counter * 10:D2}

and


{counter * 10 + 9:D2}

to format the label of the grade range. The format specifier D indicates that the value should be formatted as an integer, and the number after the D indicates how many digits this formatted integer must contain. The 2 indicates that values with fewer than two digits should begin with a leading 0.

The nested for statement (lines 27–30) displays the bars. Note the loop-continuation condition at line 27 (stars < array[counter]). Each time the app reaches the inner for, the loop counts from 0 up to one less than array[counter], thus using a value in array to determine the number of asterisks to display. In this example, array[0]array[5] contain 0s because no students received a grade below 60. Thus, the app displays no asterisks next to the first six grade ranges.

Implicitly Typed Local Variables and Keyword var

In line 14


for (var counter = 0; counter < array.Length; ++counter)

notice var keyword rather than a type preceding the variable counter. This declares the variable and lets the compiler determine the variable’s type, based on the variable’s initializer. This process is known as type inference and local variables declared in this manner are known as implicitly typed local variables. Here, the compiler infers that counter’s type is int, because it’s initialized with the literal 0, which is an int.

Similarly, consider line 11 of Fig. 4.9:


Account account1 = new Account("Jane Green");

Notice that the type Account appears twice—once to declare variable account1’s type and once to specify the type of the new object being created. From this point forward, the preferred way to write this statement is


var account1 = new Account("Jane Green");

Here, the compiler infers that account1’s type is Account, because the compiler can determine the type from the expression


new Account("Jane Green")

which creates an Account object.

The Microsoft C# Coding Conventions


https://msdn.microsoft.com/library/ff926074

recommend using type inference when a local variable’s type is obvious, based on its initial value.4 These coding conventions are just guidelines, not requirements. In industry, your employer might have its own coding requirements that differ from Microsoft’s guidelines.

More on Implicitly Typed Local Variables

Implicitly typed local variables also can be used to initialize an array variable via an initializer list. In the following statement, the type of values is inferred as int[]:


var values = new[] {32, 27, 64, 18, 95, 14, 90, 70, 60, 37};

new[] specifies that the initializer list is for an array. The array’s element type, int, is inferred from the initializers. The following statement—in which values is initialized directly without new[]—generates a compilation error:


var values = {32, 27, 64, 18, 95, 14, 90, 70, 60, 37};

Common Programming Error 8.6

Initializer lists can be used with both arrays and collections. If an implicitly typed local variable is initialized via an initializer list without new[], a compilation error occurs, because the compiler cannot infer whether the variable should be an array or a collection. We use a List collection in Chapter 9 and cover collections in detail in Chapter 21.

8.4.7 Using the Elements of an Array as Counters

Sometimes, apps use counter variables to summarize data, such as the results of a survey. In Fig. 7.7, we used separate counters in our die-rolling app to track the number of times each face of a six-sided die appeared as the app rolled the die 60,000,000 times. An array version of the app in Fig. 7.7 is shown in Fig. 8.8.

Fig. 8.8 Roll a six-sided die 60,000,000 times.

Alternate View

  1   // Fig. 8.8: RollDie.cs
  2   // Roll a six-sided die 60,000,000 times.
  3   using System;
  4
  5   class RollDie
  6   {
  7      static void Main()
  8      {
  9         var randomNumbers = new Random(); // random-number generator
 10         var frequency = new int[7]; // array of frequency counters
 11
 12         // roll die 60,000,000 times; use die value as frequency index
 13         for (var roll = 1; roll <= 60000000; ++roll)
 14         {
 15            ++frequency[randomNumbers.Next(1, 7)];
 16         }
 17
 18         Console.WriteLine($"{"Face"}{"Frequency",10}");
 19
 20         // output each array element's value
 21         for (var face = 1; face < frequency.Length; ++face)
 22         {
 23            Console.WriteLine($"{face,4}{frequency[face],10}");
 24         }
 25      }
 26   }

Face Frequency
   1  10004131
   2   9998200
   3  10003734
   4   9999332
   5   9999792
   6   9994811

The app uses array frequency (line 10) to count the occurrences of each roll. The single statement in line 15 replaces lines 24–44 of Fig. 7.7. Line 15 of Fig. 8.8 uses the random value to determine which frequency array element to increment. The call to Next produces a random number from 1 to 6, so frequency must be large enough to store six counters. We use a seven-element array in which we ignore frequency[0]—it’s more logical to have the face value 1 increment frequency[1] than frequency[0]. Thus, each face value is used directly as an index for array frequency. We also replaced lines 48–50 of Fig. 7.7 by looping through array frequency to output the results (Fig. 8.8, lines 21–24).

..................Content has been hidden....................

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