7.6. Arrays And Loops

Time: 00:03:00 | Download: Large, Large (CC), Small | Streaming, Streaming (CC) | Slides (PDF)

The elements in an array are accessed by sequential index numbers ranging from 0 to one less than the size of the array. This indexing scheme lends itself to iterative access or processing driven by a for-loop and using the loop control variable as the array index.

int	test[10];

for (int i = 0; i < 10; i++)
	cout << test[i] << endl;

float	test_score[10][4];

for (int i = 0; i < 10; i++)
	for (int j = 0; j < 4; j++)
		cout << test_score[i][j] << endl;
One-Dimensional ArrayTwo-dimensional Array
Processing arrays with for-loops. The patterns found in the examples suggest three common programming practices:
  1. Typically, there is one for loop for each array dimension.
  2. C++ arrays are zero indexed, so programmers start the for-loop control variable at 0 and use a strict less-than test in the middle expression, which causes the loop to end after the last element is processed.
  3. It is important to ensure that the loops and the indexes are correctly aligned. In the two-dimensional array example, the first dimension size is 10, and the second size is 4. The outer loop accesses the first or row dimension and iterates from 0 through 9; the inner loop accesses the second or column dimension and iterates from 0 through 3.

The size of an array is fixed when the program creates it. This observation holds for both automatic and dynamic arrays. Sometimes, we know how many elements an array needs so it doesn't run out of or waste space. However, when we take data directly from user input or a file, we generally don't know how many data items the program will read. So, if we store the data in an array, we don't know how big to make it, and we can't change its size while the program runs. How do we solve this problem?

The only situation worse than wasting space in an array is running out of space! So, we use a technique common to many engineering disciplines: design for the worst-case scenario and then over-engineer the solution (i.e., add an extra safety margin). Some engineering disciplines have well-accepted rules of thumb for various safety margins, but software engineering generally lacks these rules. Nevertheless, in most contemporary computing environments, main memory is relatively ample and inexpensive, which argues for a generous safety margin.

Although a program establishes the size of an array when making it, it is not required to use every array element. In practice, we start filling the array at the beginning - at element 0 - and continue adding data sequentially until all data is stored. It's important to count how many elements the program fills, which requires an additional counter variable. This approach is useful when reading data from a file (illustrated in a later chapter) or entered by a user.

int	scores[100];
int	score;
int	count = 0;

cout << "Enter a score (-1 to stop): ";

cin >> score;
while (score != -1)
{
	scores[count++] = score;
	cin >> score;
}
int	scores[100];
int	count = 0;

cout << "Enter a score (-1 to stop): ";

do
{
	cin >> scores[count++];
} while (scores[count - 1] != -1);
count--;		// discard the -1


Arrays and indeterminate loops. Indeterminate loops iterate an unknown or indeterminate number of times and are often implemented with either a do- or a do-while-loop. The loops in this example count the number of data items as they are entered and stored in the array, which we assume are larger than the maximum number of data items entered. (We will revisit this assumption later in this chapter.)
for (int i = 0; i < count; i++)
	cout << array[i] << endl;
Arrays and counting loops. If we know how many loop iterations we need before the loop begins, a for-loop is the best choice. In this example, the array is larger than needed, meaning some array elements are unused. The variable count drives the for-loop, so the program only accesses the filled array elements and ignores the unused elements.

Copying Arrays

We previously explored array assignment where we learned that assignment alone cannot copy an array. Nevertheless, it is sometimes necessary to copy an array, so how can we do it? It takes two steps to copy an array. First, we create a new array large enough to hold all the elements in the original array. Second, we copy the elements from the original array to the new one, one element at a time, as illustrated in the following figure.

Following the assignment operation, pointer p2 points to the array scores. The picture begins with scores as an array. Next, the program creates another array with the new operator and saves its address in p2. Finally, each element is copied from scores to p2 with a for-loop.
int	scores[50];
int*	p2 = scores;


int	scores[50];
int*	p2 = new int[50];
for (int i = 0; i < 50; i++)
	p2[i] = scores[i];
(a)(b)
p2 and scores are two separate arrays. The for-loop copies each element of scores to p2. p1 and p2 are pointer parameters of the copy function. They each point to an array.
int	scores[50];
int	p2[50];
for (int i = 0; i < 50; i++)
	p2[i] = scores[i];
void copy (int* p2, int p* p1, int size)
{
	...
}
(c)(d)
Copying an array. It's easier to understand the code fragments illustrated here if you recall that an array's name is also its address in memory.
  1. Assignment stores the address represented by the name scores in the pointer variable p2, which only gives the original array another name or an alias. In this example, the new array is allocated dynamically on the heap.
  2. Copying an array requires two steps: (1) create a new array and (2) copy the elements from the original array to the new array.
  3. The new array may also be allocated on the stack, as is illustrated here.
  4. Recall that arrays are always passed as function arguments by pointer. It is possible for a function to copy an array if two per-conditions are satisfied: (1) the new array, p2, is large enough to hold the copied data, and (2) one of the function arguments is the number of elements that the function should copy.
By adjusting the starting and ending points of the for-loop, it's possible to copy just a part of the original array.