7.8 Multidimensional arrays

You can use arrays with two dimensions (i.e., subscripts) to represent tables of values consisting of information arranged in rows and columns. To identify a particular table element, we must specify two subscripts—by convention, the first identifies the element’s row and the second identifies the element’s column. arrays that require two subscripts to identify a particular element are called two-dimensional arrays or 2-D arrays. arrays with two or more dimensions are known as multidimensional arrays. Figure 7.16 illustrates a two-dimensional array, a. The array contains three rows and four columns, so it’s said to be a 3-by-4 array. In general, an array with m rows and n columns is called an m-by-narray.

Fig. 7.16 Two-dimensional array with three rows and four columns.

Every element in array a is identified in Fig. 7.16 by an element name of the form a[i][j], where a is the name of the array, and i and j are the subscripts that uniquely identify each element in a. Notice that the names of the elements in row 0 all have a first subscript of 0; the names of the elements in column 3 all have a second subscript of 3.

Common Programming Error 7.5

Referencing a two-dimensional array element a[x][y] incorrectly as a[x, y] is an error. Actually, a[x, y] is treated as a[y], because C++ evaluates the expression x, y (containing a comma operator) simply as y (the last of the comma-separated expressions).

Figure 7.17 demonstrates initializing two-dimensional arrays in declarations. Lines 12–13 each declare an array of arrays with two rows and three columns. Notice the nested array type declaration. In each array, the type of its elements is specified as


array<int, columns>

indicating that each array contains as its elements three-element arrays of int values— the constant columns has the value 3.

Fig. 7.17 Initializing multidimensional arrays.

Alternate View

 1   // Fig. 7.17: fig07_17.cpp
 2   // Initializing multidimensional arrays.
 3   #include <iostream>
 4   #include <array>
 5   using namespace std;
 6
 7   const size_t rows{2};
 8   const size_t columns{3};
 9   void printArray(const array<array<int, columns>, rows>&);
10
11   int main() {
12      array<array<int, columns>, rows> array1{1, 2, 3, 4, 5, 6};
13      array<array<int, columns>, rows> array2{1, 2, 3, 4, 5};   
14
15      cout << "Values in array1 by row are:" << endl;
16      printArray(array1);
17
18      cout << "
Values in array2 by row are:" << endl;
19      printArray(array2);
20   }
21
22   // output array with two rows and three columns
23   void printArray(const array<array<int, columns>, rows>& a) {
24      // loop through array's rows
25      for (auto const& row : a) {
26         // loop through columns of current row
27         for (auto const& element : row) {
28            cout << element << ' ';
29         }
30
31         cout << endl; // start new line of output
32      }
33   }

Values in array1 by row are:
1 2 3
4 5 6

Values in array2 by row are:
1 2 3
4 5 0

The declaration of array1 (line 12) provides six initializers. The compiler initializes the elements of row 0 followed by the elements of row 1. So, the first three values initialize row 0’s elements to 1, 2 and 3, and the last three initialize row 1’s elements to 4, 5 and 6. The declaration of array2 (line 13) provides only five initializers. The initializers are assigned to row 0, then row 1. Any elements that do not have an explicit initializer are initialized to zero, so array2[1][2] is 0.

The program calls function printArray to output each array’s elements. Notice that the function prototype (line 9) and definition (lines 23–33) specify that the function receives a two-row and three-column array. The parameter receives the array by reference and is declared const because the function does not modify the array’s elements.

Nested Range-Based for Statements

To process the elements of a two-dimensional array, we use a nested loop in which the outer loop iterates through the rows and the inner loop iterates through the columns of a given row. Function printArray’s nested loop is implemented with range-based for statements. Lines 25 and 27 introduce the C++11 auto keyword, which tells the compiler to infer (determine) a variable’s data type based on the variable’s initializer value. The outer loop’s range variable row is initialized with an element from the parameter a. Looking at the array’s declaration, you can see that the array contains elements of type


array<int, columns>

so the compiler infers that row refers to a three-element array of int values (again, columns is 3). The const& in row’s declaration indicates that the reference cannot be used to modify the rows and prevents each row from being copied into the range variable. The inner loop’s range variable element is initialized with one element of the array represented by row, so the compiler infers that element refers to an int because each row contains three int values. In an IDE, you can typically hover your mouse over a variable declared with auto and the IDE will display the variable’s inferred type. Line 28 displays the value from a given row and column.

Nested Counter-Controlled for Statements

We could have implemented the nested loop with counter-controlled iteration as follows:


for (size_t row{0}; row < a.size(); ++row) {
   for (size_t column{0}; column < a[row].size(); ++column) {
      cout << a[row][column] << ' ';
   }

   cout << endl;
}

Other Common Two-Dimensional array Manipulations

The following for statement sets all the elements in row 2 of array a in Fig. 7.16 to zero:


for (size_t column{0}; column < 4; ++column) {
   a[2][column] = 0;
}

The for statement varies only the second subscript (i.e., the column subscript). The preceding for statement is equivalent to the following assignment statements:


a[2][0] = 0;
a[2][1] = 0;
a[2][2] = 0;
a[2][3] = 0;

The following nested counter-controlled for statement determines the total of all the elements in array a in Fig. 7.16:


total = 0;
for (size_t row{0}; row < a.size(); ++row) {
   for (size_t column{0}; column < a[row].size(); ++column) {
      total += a[row][column];
   }
}

The for statement totals the elements of the array one row at a time. The outer for statement begins by setting row (i.e., the row subscript) to 0, so the elements of row 0 may be totaled by the inner for statement. The outer for statement then increments row to 1, so the elements of row 1 can be totaled. Then, the outer for statement increments row to 2, so the elements of row 2 can be totaled. When the nested for statement terminates, total contains the sum of all the array elements. This nested loop can be implemented with range-based for statements as:


total = 0;
for (auto row : a) { // for each row
   for (auto column : row) { // for each column in row
      total += column;
   }
}
..................Content has been hidden....................

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