Activity 10-1 - Introduction to Arrays



So far all of our variables have been able to hold only one value at any one point in time. Such variables are called scalar variables. Now it is time for our first non-scalar variable, an array.

An array is a variable capable of storing multiple values. When we declare an array we tell the compiler how many values we want the array to hold. We also tell the compiler what type of values the array can store. All of the values in an array must be of the same type.

Here is a declaration of an array called numlist that will be used to store 8 integers:

int numlist[8];       // declaring an integer array that can store 8 values
Each of the integers in the array is stored in the same number of bytes as a scalar integer, which on most machines is 4 bytes. Thus, the entire array will occupy 32 bytes of memory. The compiler always stores an array in contiguous memory locations (all of the elements of the array are stored in one chunk of memory with no gaps).  Here is one way you may visualize the above array numlist when it stores the following 8 integers: 12,  8, 10, 123, 1000, 23, 4, 10
 
Imaginary
Memory
Address
1023
1024
1025
1026
1027
1028
1029
1030
Array Index
0
1
2
3
4
5
6
7
Indexed
numlist Variable
numlist[0]
numlist[1]
numlist[2]
numlist[3]
numlist[4]
numlist[5]
numlist[6]
numlist[7]
Array
Content
12
8
10
123
1000
23
4
10

The individual values stored in an array are called the elements of the array. You will also hear them called indexed variables or subscripted variables. Each of the elements of an array is assigned an index. An index is a natural number in the range {0,1,2,...}.  Note that the array index started from 0.

As it is shown in the above table, to access one of the elements of an array, you put the index of that element in square brackets after the name of the array. The 0th element in the array called numlist is numlist[0], the next one is numlist[1], and so forth. Since we start the numbering with 0, the last element in numlist is numlist[7].

To put the value of 12 into the 0th element of numlist, we will use:

numlist[0] = 12;
If we wanted to store a value that is entered from the keyboard into element numlist[1] we use:
cin >> numlist[1];
An array element like numlist[4] can be used in any way that a scalar variable can be used. All of the following statements are legal:
if(numlist[2] > numlist[1]) // Compares the third element of the array with
                            // the second element of the array
cout << numlist[5];         // Displays the sixth element of the array

sum = sum + numlist[7];     // Adds the 8th element to sum
The index inside the square brackets does not have to be an integer constant such as 3 or 4.  It can be any integral expression that evaluates to an integer within the permitted range of the array's index. So an expression such as this:

for(i = 0; i < 3; i++)
     numlist[2*i+1] = 0;  // set the odd elements of the array to 0

If you wish to fill the array numlist with the integers typed from the keyboard, you can use a for loop too. Here is a for loop that will allow you to enter 8 values from the keyboard and will store them in the array numlist. Notice that we have used the variable i as an index for array numlist.

for (i=0; i<8; ++i)
{
        cout << "Enter the next value: ";
        cin >> numlist[i];
}
It might be easier for our user to keep up with different values that need to be entered if we display something more helpful than "Enter the next value: ".  Since users typically number items in a list starting from 1, we will say "Enter value #1: " when asking for numlist[0], "Enter value #2: " when asking for numlist[1], and so forth. Here is the improved vrsion of the loop:
for (i=0; i<8; ++i)
{
        cout << "Enter value #" << i+1 << ": ";
        cin >> numlist[i];
}
By asking for value 1, then value 2, etc., we are allowing our user to count in a more natural way than C++ forces us to count.  That is the most confusing part of working with arrays.  It is natural to think that an array of size 8 will keep 8 values, thus, assuming that the indices would be 1 through 8.  For an array of size 8, index 1 is a valid index, but index 8 is invalid and will cause a run-time error if it is used.

The following program allows you to enter 8 integers from the keyboard and will store those values in array numlist.

// P10_1.cpp - A program that uses an array of integers
#include <iostream>
using namespace std;
int main(void)
{
        int numlist[8], i;

        // Read 8 integers from the keyboard
        for (i = 0; i<8; i++ )
        {
                cout << "Enter value #" << i+1 << ": ";
                cin >> numlist[i];
        }
        // Display the numbers in a reverse order
        for (i = 8; i > 0; i-- )
        {
                cout << "Value #" << i << ": ";
                cout << numlist[i-1] << endl;  //Pay attention to i-1!
        }

        return 0;
}

Array Index Out of Range

A common error when working with an array is attempting to access an element of the array using an index that is out of range. In the above program, array numlist has 8 elements. The final value is called numlist[7]. If we try to access numlist[8], most C++ compilers will not give us an error message at run time. C++ does not verify that your index is within the proper range when you compile the program. If you print the value of numlist[8], the compiler will grab the 4 bytes following numlist[7], interpret whatever is stored there as an integer and print the value of that integer. If you store a value at numlist[8], the compiler will place that value into the first 4 bytes following numlist[7], even if those bytes happen to be storing a different variable! That is what happens in the following program.

// P10_1a.cpp - This program illustrates array index out of range.

#include <iostream>
using namespace std;
int main(void)
{
        int numlist[8], i;

        cout << " \t i \t numlist[i] \n";
        cout << " \t ===== \t ======== \n";

        for (i = 0; i <= 8; i++)
        {
                numlist[i] = i*2;
                cout << " \t " << i << "\t " << numlist[i] << endl;
        }
        return 0;
}

Here is the output of this program:
        i               numlist[i]
        =====    ========
         0             0
         1             2
         2             4
         3             6
         4             8
         5            10
         6            12
         7            14
         16          1      // Do you see any thing wrong here?

Initializing Arrays

A scalar variable can be initialized when it is declared, like this:
int num = 4;
An array can also be initialized when it is declared. Here we put the value 0 into numlist[0], the value 1 into numlist[1], etc.:

int numlist[8] = {12,  8, 10, 123, 1000, 23, 4, 10};

If you list fewer values within the braces { and } than the declared size (8 in the above example) of the array, our C++ compiler will initialize all the rest of the elements to 0. However, not all C++ compilers will do this. If you initialize an array when it is declared, you can omit the size of the array. C++ will use the number of initializers in your list as the size of the array. Here is an example:

char vowels[] = {'a', 'e', 'i', 'o', 'u'};
This declared a character array of size 5 which stores the lowercase vowels, a, e, i, o, and u.

Creating Arrays of Flexible Size
One way to create an array with a particular size is to use a global variable to define the size of that array. Thus, every time one can change that number to increase or decrease the size of an array.  This requires you to recompile the program for the new size to take effect.  Let's modify program 10_1.cpp to work on flexible size arrays.

// P10_1b.cpp - A program that uses a flexible size array of integers
#include <iostream>
using namespace std;
const int SIZE = 8;  // Set the maximum size for the array

int main(void)
{
        int numlist[SIZE];

        // Read SIZE integers from the keyboard
        for (int i = 0; i<SIZE; i++ )
        {
                cout << "Enter value #" << i+1 << ": ";
                cin >> numlist[i];
        }
        // Display the numbers in a reverse order
        for (int i = SIZE; i > 0; i-- )
        {
                cout << "Value #" << i << ": ";
                cout << numlist[i-1] << endl;  //Pay attention to i-1!
        }

        return 0;
}

This produces the same result as P10_1.cpp.  Now, you are limited to array of 8 integers.  By changing the value for SIZE, you can read as many numbers as you wish.

Exercise 10.1
Modify program P10_1b.cpp such that it reads some number of integers as defined by SIZE, stored them in array numlist, displays the array numlist, then reverses the contents of the array, and at last displays the contents of that array again.

Make your program as general as possible.  Thus, your program should be able to reverse the contents of an array of any size defined by SIZE.  Note that we didn't ask you to display the array in reverse, that would be what program P10_2.cpp is doing.  We want you to reverse the contents of the array, then display the array itself.  Example:

int A = {1, 2, 4, 5, 8, 2, 0, 9};

After you reverse the contents of array A, that array would become: {9, 0, 2, 8, 5, 4, 2, 1}.  So, you will display the array A before you reverse the content and after you reversed the contents.