Two Indexes are Better than One.
FOUND ON THE WALL OF A COMPUTER SCIENCE DEPARTMENT RESTROOM
C++ allows you to declare arrays with more than one index. In this section we describe these multidimensional arrays.
It is sometimes useful to have an array with more than one index, and this is allowed in C++. The following declares an array of characters called page
. The array page
has two indexes: The first index ranges from 0
to 29
, and the second from 0
to 99
.
char
page[30][100];
The indexed variables for this array each have two indexes. For example, page[0][0]
, page[15][32]
, and page[29][99]
are three of the indexed variables for this array. Note that each index must be enclosed in its own set of square brackets. As was true of the one-dimensional arrays we have already seen, each indexed variable for a multidimensional array is a variable of the base type.
An array may have any number of indexes, but perhaps the most common number of indexes is two. A two-dimensional array can be visualized as a two-dimensional display with the first index giving the row and the second index giving the column. For example, the array indexed variables of the two-dimensional array page
can be visualized as follows:
page[0][0], page[0][1], ..., page[0][99]
page[1][0], page[1][1], ..., page[1][99]
page[2][0], page[2][1], ..., page[2][99]
.
.
.
page[29][0], page[29][1], ..., page[29][99]
You might use the array page
to store all the characters on a page of text that has 30 lines (numbered 0 through 29) and 100 characters on each line (numbered 0 through 99).
In C++, a two-dimensional array, such as page
, is actually an array of arrays. The example array page
is actually a one-dimensional array of size 30, whose base type is a one-dimensional array of characters of size 100. Normally, this need not concern you, and you can usually act as if the array page
is actually an array with two indexes (rather than an array of arrays, which is harder to keep track of). There is, however, at least one situation where a two-dimensional array looks very much like an array of arrays, namely, when you have a function with an array parameter for a two-dimensional array, which is discussed in the next subsection.
The following declaration of a two-dimensional array is actually declaring a one-dimensional array of size 30, whose base type is a one-dimensional array of characters of size 100:
char
page[30][100];
Viewing a two-dimensional array as an array of arrays will help you to understand how C++ handles parameters for multidimensional arrays. For example, the following function takes an array argument, like page
, and prints it to the screen:
void
displayPage(const char
p[][100],
int
sizeDimension1) {
for
(int
index1 = 0; index1 < sizeDimension1; index1++) {//Printing one line:
for
(int
index2 = 0; index2 < 100; index2++) cout << p[index1][index2]; cout << endl; } }
Notice that with a two-dimensional array parameter, the size of the first dimension is not given, so we must include an int
parameter to give the size of this first dimension. (As with ordinary arrays, the compiler will allow you to specify the first dimension by placing a number within the first pair of square brackets. However, such a number is only a comment; the compiler ignores any such number.) The size of the second dimension (and all other dimensions if there are more than two) is given after the array parameter, as shown for the parameter
const char
p[ ][100]
If you realize that a multidimensional array is an array of arrays, then this rule begins to make sense. Since the two-dimensional array parameter
const char
p[ ][100]
is a parameter for an array of arrays, the first dimension is really the index of the array and is treated just like an array index for an ordinary, one-dimensional array. The second dimension is part of the description of the base type, which is an array of characters of size 100.
Display 7.14 contains a program that uses a two-dimensional array, named grade
, to store and then display the grade records for a small class. The class has four students and includes three quizzes. Display 7.15 illustrates how the array grade
is used to store data. The first array index is used to designate a student, and the second array index is used to designate a quiz. Since the students and quizzes are numbered starting with 1 rather than 0, we must subtract 1 from the student number and subtract 1 from the quiz number to obtain the indexed variable that stores a particular quiz score. For example, the score that student number 4 received on quiz number 1 is recorded in grade[3][0]
.
Our program also uses two ordinary one-dimensional arrays. The array stAve
will be used to record the average quiz score for each of the students. For example, the program will set stAve[0]
equal to the average of the quiz scores received by student 1, stAve[1]
equal to the average of the quiz scores received by student 2, and so forth. The array quizAve
will be used to record the average score for each quiz. For example, the program will set quizAve[0]
equal to the average of all the student scores for quiz 1, quizAve[1]
will record the average score for quiz 2, and so forth. Display 7.16 illustrates the relationship between the arrays grade
, stAve
, and quizAve
. In that display, we have shown some sample data for the array grade
. This data, in turn, determines the values that the program stores in stAve
and in quizAve
. Display 7.16 also shows these values, which the program computes for stAve
and quizAve
.
Two-Dimensional Array
1
//Reads quiz scores for each student into the two-dimensional array grade (but
2
//the input code is not shown in this display). Computes the average score
3
//for each student and the average score for each quiz. Displays the quiz scores
4
//and the averages.
5 #include <iostream> 6 #include <iomanip> 7
const int
NUMBER_STUDENTS = 4, NUMBER_QUIZZES = 3; 8 9
void
computeStAve(const int
grade[][NUMBER_QUIZZES],
double
stAve[]); 10
//Precondition: Global constants NUMBER_STUDENTS and NUMBER_QUIZZES
11
//are the dimensions of the array grade. Each of the indexed variables
12
//grade[stNum − 1, quizNum − 1] contains the score for student stNum on quiz
13
//quizNum.
14
//Postcondition: Each stAve[stNum − 1] contains the average for student
15
//number stuNum.
16 17
void
computeQuizAve(const int
grade[][NUMBER_QUIZZES],
double
quizAve[]); 18
//Precondition: Global constants NUMBER_STUDENTS and NUMBER_QUIZZES
19
//are the dimensions of the array grade. Each of the indexed variables
20
//grade[stNum − 1, quizNum − 1] contains the score for student stNum on quiz
21
//quizNum.
22
//Postcondition: Each quizAve[quizNum − 1] contains the average for quiz number
23
//quizNum.
24 25
void
display(const int
grade[][NUMBER_QUIZZES], 26
const double
stAve[],
const double
quizAve[]); 27
//Precondition: Global constants NUMBER_STUDENTS and NUMBER_QUIZZES are the
28
//dimensions of the array grade. Each of the indexed variables grade[stNum − 1,
29
//quizNum − 1] contains the score for student stNum on quiz quizNum. Each
30
//stAve[stNum − 1] contains the average for student stuNum. Each
31
//quizAve[quizNum − 1] contains the average for quiz number quizNum.
32
//Postcondition: All the data in grade, stAve, and quizAve has been output.
33 34
int
main( ) 35 { 36
using namespace
std; 37
int
grade[NUMBER_STUDENTS][NUMBER_QUIZZES]; 38
double
stAve[NUMBER_STUDENTS]; 39
double
quizAve[NUMBER_QUIZZES]; 40 <The code for filling the array grade goes here, but is not shown.> 41 computeStAve(grade, stAve); 42 computeQuizAve(grade, quizAve); 43 display(grade, stAve, quizAve); 44
return
0; 45 } 46
void
computeStAve(const int
grade[][NUMBER_QUIZZES],
double
stAve[]) 47 { 48
for
(int
stNum = 1; stNum <= NUMBER_STUDENTS; stNum++) 49 {//Process one stNum:
50
double
sum = 0; 51
for (int quizNum = 1; quizNum <= NUMBER_QUIZZES; quizNum++) 52 sum = sum + grade[stNum − 1][quizNum − 1]; 53 //sum contains the sum of the quiz scores for student number stNum. 54 stAve[stNum − 1] = sum/NUMBER_QUIZZES; 55 //Average for student stNum is the value of stAve[stNum−1]
56 } 57 } 58 59 60
void
computeQuizAve(const int
grade[][NUMBER_QUIZZES],
doublequizAve[]) 61 { 62
for
(int
quizNum = 1; quizNum <= NUMBER_QUIZZES; quizNum++) 63 {//Process one quiz (for all students):
64
double
sum = 0; 65
for (int stNum = 1; stNum <= NUMBER_STUDENTS; stNum++) 66 sum = sum + grade[stNum − 1][quizNum − 1]; 67 //sum contains the sum of all student scores on quiz number quizNum. 68 quizAve[quizNum − 1] = sum/NUMBER_STUDENTS; 69 //Average for quiz quizNum is the value of quizAve[quizNum − 1]
70 } 71 } 72 73 74
//Uses iostream and iomanip:
75
void
display(const int
grade[][NUMBER_QUIZZES], 76
const double
stAve[],
const double
quizAve[]) 77 { 78
using namespace
std; 79 cout.setf(ios::fixed); 80 cout.setf(ios::showpoint); 81 cout.precision(1); 82 cout << setw(10) << "Student" 83 << setw(5) << "Ave" 84 << setw(15) << "Quizzes\n"; 85
for
(int
stNum = 1; stNum <= NUMBER_STUDENTS; stNum++) 86 {//Display for one stNum: 87 cout << setw(10) << stNum 88 << setw(5) << stAve[stNum − 1] << " "; 89
for
(int
quizNum = 1; quizNum <= NUMBER_QUIZZES; quizNum++) 90 cout << setw(5) << grade[stNum − 1][quizNum − 1]; 91 cout << endl; 92 } 93 cout << "Quiz averages = "; 94
for
(int
quizNum = 1; quizNum <= NUMBER_QUIZZES; quizNum++) 95 cout << setw(5) << quizAve[quizNum − 1]; 96 cout << endl; 97 }
Sample Dialogue
<The dialogue for filling the array grade is not shown.>
Student |
Ave |
Quizzes |
||
1 |
10.0 |
10 |
10 |
10 |
2 |
1.0 |
2 |
0 |
1 |
3 |
7.7 |
8 |
6 |
9 |
4 |
7.3 |
8 |
4 |
10 |
Quiz averages = |
7.0 |
5.0 |
7.5 |
The complete program for filling the array grade
and then computing and displaying both the student averages and the quiz averages is shown in Display 7.14. In that program we have declared array dimensions as global named constants. Since the procedures are particular to this program and could not be reused elsewhere, we have used these globally defined constants in the procedure bodies, rather than having parameters for the size of the array dimensions. Since it is routine, the display does not show the code that fills the array.
What is the output produced by the following code?
int
myArray[4][4], index1, index2;
for
(index1 = 0; index1 < 4; index1++)
for
(index2 = 0; index2 < 4; index2++) myArray[index1][index2] = index2;
for
(index1 = 0; index1 < 4; index1++) {
for
(index2 = 0; index2 < 4; index2++) cout << myArray[index1][index2] << " "; cout << endl; }
Write code that will fill the array a
(declared below) with numbers typed in at the keyboard. The numbers will be input five per line, on four lines (although your solution need not depend on how the input numbers are divided into lines).
int
a[4][5];
Write a function definition for a void
function called echo
such that the following function call will echo the input described in Self-Test Exercise 21 and will echo it in the same format as we specified for the input (that is, four lines of five numbers per line):
echo(a, 4);