Lab 10 -- Arrays

In this lab we will learn about

Getting Ready

First create a subdirectory called lab10 under your 1440 directory, then change to that subdirectory.

Introduction to Arrays

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

An array is one 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];       // 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 our cs machine 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.)

Accessing Individual Array Elements

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,...}.

In C++, all arrays are indexed starting from 0. 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 begin numbering with 0, the last element in numlist is numlist[7].

To put a value of 17 into the 0th element of numlist, we would say

numlist[0] = 17;
If we wanted to have the user input a value to be stored in numlist[1] we would say
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 are legal ways to use an array element.
if (numlist[2] > numlist[1]) ...
 
cout << numlist[5];
 
sum = sum + numlist[7];
The index inside the square brackets does not have to be an integer constant like 3 or 4. It can be any integral expression that evaluates to an integer within the range of the array's indexes.

Suppose we wish to fill our array, numlist, with integers typed at the keyboard. A for loop is an easy way to do that. Here is a for loop that will allow the user to enter values that will be stored in numlist. Notice that we have used the variable i as an index to 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 the different values to be entered if we print 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 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.

Copy the following program to a file called p1.C, then run it to see that it allows you to enter 8 values.

#include <iostream.h>
 
int main(void)
{
        int numlist[8], i;
 
        for (i=0; i<8; ++i)
        {
                cout << "Enter value #" << i+1 << ": ";
                cin >> numlist[i];
        }
        return 0;
}
Now edit the program so that after all the values are entered, they are printed out. Use a for loop and output one value per line. Make your program's output look like this with the xx's replaced by the values you entered:
Value #1 is xx
Value #2 is xx
...
Value #8 is xx

Array Index Out of Range

A common error when working with an array is attempting to access an element of the array but using an index that is out of range. In the above program, numlist has 8 values. The final value is called numlist[7]. If we try to access numlist[8], most C++ compilers (ours included) will not give us an error message. C++ does not verify that your index is within the proper range. 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.

This program contains an error that causes it to use an index outside of the range 0..7. Copy the program to p2.C, compile and run it. Be sure you understand why the variable x, which is set to 1 initially, gets changed to 8.

#include <iostream.h>
 
int main(void)
{
        int numlist[8], x, y, i;
 
        x = 1;
        y = 2;
        cout << "x is " << x << " and y is " << y << endl;
        for (i=0; i<=8; ++i)
                numlist[i] = i;
        for (i=0; i<8; ++i)
                cout << "numlist[" << i << "] is " << numlist[i] << endl;
        cout << "x is " << x << " and y is " << y << endl;
 
        return 0;
}
Now edit the program and correct that error.

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] = {0,1,2,3,4,5,6,7};
If you list fewer values within the braces than there are elements 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. The code
char vowels[] = {'a', 'e', 'i', 'o', 'u'};
creates a character array of size 5 which contains the lowercase vowels.

Lab work

Write a C++ code that ask users to inpute 10 characters (letters or numbers) then displays the orginal 10 numbers on one line and the numbers in reverse order on the next line.

Homework - Due Monday Nov. 19

Write a program which reads a list of integers from a user-specified input file  and outputs the list with duplicates removed to a user-specified output file. That is, any value which occurs at least once in the input file should occur once and only once in the output file and that the position of occurrence will be determined by the relative positive of the first occurrence in the original input file. You may assume that there are no more than 100 numbers in the input file. This means that you should allocate space for 100 numbers as in
int data[100];
but keep track of the actual numbers read.

For example, suppose that the input file contains these values:

2  8  3  4  6  8  2  1 4  1  1  1 6  5  5
the output file with duplicates removed should be
2  8  3  4  6  1 5
Here are the function prototypes for the functiuons that you are required to use:

void open_input_file(ifstream &input_file);
// Prompts the user for the name of the input file
// and attempts to open the file.
// If the file cannot be opened successfully, the user
// is given two options:
//  - try another file name
//  - exit the program

void open_output_file(ofstream &output_file);
// Prompts the user for the name of the output file
// and attempts to open the file.
// If the file cannot be opened successfully, the user
// is given two options:
//  - try another file name
//  - exit the program

void read_array_data(ifstream &input_file, int data[], int & data_size);
// Reads integer data from the input file stream and stores sequentially
// in the array data[].  Input halts at the end of file or when the
// array is filled, in which case all other data in the file is
// ignored.  This function returns the actual number of values stored
// in the array data[] by changing the parameter data_size.

void save_array_data(ifstream &output_file, int data[], int data_size);
// Write integer data from the array data[] to the output file stream.
// The parameter data_size specifies the number of items to be written.
// It is required that data_size be <= the actual array size.

void remove_duplicates(int data[], int & data_size);
// Removes all duplicate elements from the integer array data[].
// The value of data size will be reduced if duplicates are removed.
// It is required that data_size be <= the actual array size.

void find_duplicate position(int data[], int data_size, int element_index,
                            int search_index);
// This function searches the integer array data for a duplicate
// of the item data[element_index] starting the search at search_index
// through index data_size-1.  The index of the first duplicate
// found is returned as the modified search_index.  If no duplicates are
// found OR if search_index is <= element_index, then -1 is returned as
// the value of search_index.
// It is required that data_size be <= the actual array size.

void remove_item(int data[], int & data_size, int remove_index);
// Removes the item at position remove_index and moves all
// subsequent elements one position forward.  If remove_index
// is negative or greater than data_size-1, the array is
// not changed.  The data_size is decremented if an item is removed.
// It is required that data_size be <= the actual array size.