for
loop with an arrayYou can find the wrox.com code downloads for this chapter on the Download Code tab at www.wrox.com/go/beginningvisualc. The code is in the Chapter 4 download and individually named according to the names throughout the chapter.
You already know how to define and initialize variables of various types that each holds a single item of information; I’ll refer to single items of data as data elements. The most obvious extension to the idea of a variable is to be able to reference several data elements of a particular type with a single variable name. This would enable you to handle applications of a much broader scope.
Let’s consider an example. Suppose that you needed to write a payroll program. Using a separate variable for each individual’s pay, tax liability, and so on, would be an uphill task to say the least. A more convenient way to handle such a problem would be to reference an employee by some kind of generic name — employeeName
to take an imaginative example — and to have other generic names for the kinds of data related to each employee, such as pay
and tax
. Of course, you would need some means of picking out a particular employee from the whole bunch, together with the data from the generic variables associated with them. This kind of requirement arises with any collection of like entities that you want to handle, whether they’re baseball players or battleships. Naturally, C++ provides you with a way to deal with this.
One way to solve these problems is to use an array. An array is a number of memory locations called array elements or simply elements, each of which stores an item of data of the same given data type, and which are all referenced through the same variable name. The employee names in a payroll program could be stored in one array, the pay for each employee in another, and the tax due for each employee could be stored in a third array.
You select an element in an array using an index value. An index is an integer representing the sequence number of the element in the array. The first element has the index 0
, the second 1
, and so on. You can also envisage the index for an array element as being the offset from the first element. The first element has an offset of 0
and therefore an index of 0
, and an index value of 3
will refer to the fourth element of an array.
The basic structure of an array is illustrated in Figure 4-1.
Figure 4-1 shows an array with the name height
that has six elements. These might be the heights of the members of a family, for instance, recorded to the nearest inch. Because there are six elements, the index values run from 0
through 5
. You refer to a particular element by writing the array name followed by the index value of the element between square brackets. The third element is height[2]
, for example. If you think of the index as the offset from the first element, it’s easy to see that the index for the fourth element will be 3.
The memory required to store each element is determined by its type, and all the elements of an array are stored in a contiguous block of memory.
You define an array in essentially the same way as you defined the variables that you have seen up to now. The only difference is that you specify the number of array elements between square brackets following the array name. For example, you could define the integer array height
, shown in the previous figure, with the following statement:
long height[6];
A long
value occupies 4 bytes, so the whole array requires 24 bytes. Arrays can be of any size, subject to the constraints imposed by the amount of memory in the computer on which your program is running.
Arrays can be of any type. For example, to define arrays to store the capacity and power output of a series of engines, you could write:
double engine_size[10]; // Engine size in cubic inches
double horsepower[10]; // Engine power output
If auto mechanics is your thing, this would enable you to store the cubic capacity and power output of up to 10 engines, referenced by index values from 0
to 9
. As you have seen with other variables, you can define several arrays of a given type in a single statement, but in practice it is almost always better to define them in separate statements.
To initialize an array in its definition, you put the initializing values in an initializer list. Here’s an example:
int engine_size[5] { 200, 250, 300, 350, 400 };
The array has the name engine_size
and has five elements that each store a value of type int
. The values in the initializing list correspond to successive index values, so in this case engine_size[0]
has the value 200, engine_size[1]
the value 250, engine_size[2]
the value 300, and so on.
You must not specify more initializing values than there are elements in the array, but you can include fewer. If there are fewer, the values are assigned to successive elements, starting with the first — which is the one corresponding to index 0
. Array elements for which you don’t provide a value are initialized with zero. This isn’t the same as supplying no initializing list. Without an initializing list, the array elements contain junk values. You can initialize all array elements to zero with an empty initializer list. For example:
long data[100] {}; // Initialize all elements to zero
You can also omit the dimension of an array, provided you supply initializing values. The number of array elements will be the number of initializing values. For example:
int value[] { 2, 3, 4 };
This defines an array with three elements that have initial values 2, 3
, and 4
.
You have seen that you can use a for
loop to iterate over all the elements in an array. The range-based for
loop makes this even easier. The loop is easy to understand through an example:
double temperatures[] {65.5, 68.0, 75.0, 77.5, 76.4, 73.8,80.1};
double sum {};
int count {};
for(double t : temperatures)
{
sum += t;
++count;
}
double average = sum/count;
This calculates the average of the values in the temperatures
array. The parentheses following for
contain two things separated by a colon; the first specifies the variable that will access each of the values from the collection specified by the second. The t
variable will be assigned the value of each element in the temperatures
array in turn before executing the loop body. This accumulates the sum of the array elements . The loop also accumulates the total number of elements in count
so the average can be calculated after the loop.
You could also write the loop using the auto
keyword:
for(auto temperature : temperatures)
{
sum += temperature;
++count;
}
The auto
keyword tells the compiler to determine the type for the local variable that holds the current value from the array type. The compiler knows that the array elements are of type double
, so t
will be of type double
.
You cannot modify the values of the array elements in the range-based for
loop as it is written here. You can only access the element values for use elsewhere. With the loop written as it is, element values are copied to the loop variable. You could access the array elements directly specifying the loop variable as a reference. You learn about references later in this chapter.
Arrays with one index are referred to as one-dimensional arrays. You can define an array with more than one index, in which case it is a multidimensional array. Suppose you have a field in which you are growing bean plants in rows of 10, and the field contains 12 rows so there are 120 plants in all. You could define an array to record the weight of beans produced by each plant using the statement:
double beans[12][10];
This defines the two-dimensional array beans
, the first index being the row number, and the second index the plant number within the row. To refer to an element requires two index values. For example, you could set the value of the element reflecting the fifth plant in the third row with the statement:
beans[2][4] = 10.7;
Remember that index values start from zero, so the row index is 2
and the index for the fifth plant within the row is 4
.
Being a successful bean farmer, you might have several identical fields planted with beans in the same pattern. Assuming that you have eight fields, you could use a three-dimensional array to record data about these, defined thus:
double beans[8][12][10];
This records production for the 10 plants in each of the 12 rows in a field and the leftmost index references one of the 8 fields. If you ever get to bean farming on an international scale, you can use a four-dimensional array, with the extra dimension designating the country. Assuming that you’re as good a salesman as you are a farmer, growing this quantity of beans is likely to affect the ozone layer.
Arrays are stored in memory such that the rightmost index varies most rapidly. Thus, the array data[3][4]
is three one-dimensional arrays of four elements each. The arrangement of this array is illustrated in Figure 4-2.
The elements of the array are stored in a contiguous block of memory, as indicated by the arrows in Figure 4-2. The first index selects a particular row within the array, and the second index selects an element within a row.
A two-dimensional array is really a one-dimensional array of one-dimensional arrays. An array with three dimensions is actually a one-dimensional array of elements where each element is a one-dimensional array of one-dimensional arrays. This is not something you need to worry about most of the time. However, it implies that for the array in Figure 4-2, the expressions data[0], data[1]
, and data[2]
reference one-dimensional arrays.
To initialize a multidimensional array, you use an extension of the method used for a one-dimensional array. For example, you can define and initialize a two-dimensional array, data
, with the statement:
long data[2][4] {
{ 1, 2, 3, 5 },
{ 7, 11, 13, 17 }
};
The initial values for each row are within their own pair of braces. Because there are four elements in each row, there are four initial values in each group, and because there are two rows, there are two groups between braces, each group of initial values being separated from the next by a comma.
You can omit initial values in any row, in which case the remaining elements in the row are zero. For example:
long data[2][4] {
{ 1, 2, 3 },
{ 7, 11 }
};
I have spaced out the initial values to show where values have been omitted. The elements data[0][3], data[1][2]
, and data[1][3]
have no initializing values and are therefore zero.
To initialize the entire array with zeros you can write:
long data[2][4] {};
If you are initializing arrays with even more dimensions, remember that you need as many nested braces for groups of initial values as there are dimensions in the array — unless you’re initializing the array with zeros.
You can let the compiler work out the first dimension in an array, but only the first, regardless of the number of dimensions.
An array of char
elements is called a character array and is generally used to store a C-style string. A character string is a sequence of characters with a special character appended to indicate the end of the string. This character is defined by the escape sequence