CS12 Lab 2 - part 3 - Dynamic Arrays
back to part 2

There is a close association between pointers and arrays. Recall from Lab 7 how array elements were accessed. In C++, an array variable is actually a pointer variable that points to the first indexed variable of the array. Array elements can be accessed using pointer notation as well as array notation. Recall program P10_1.cc from Lab 10:

// P10_1.cc - A program that uses an array of integers
#include <iostream>
using namespace std;
int main( )
{
   int numlist[8];
   int 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;
}

Now let's re-write the program and access the array numlist using pointer notation.

// P12_2.cc - A program that uses an array of integers. Array elements accessed using pointer notation
#include <iostream>
using namespace std;
int main(void)
{
   int numlist[8];

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

   return 0;
}

In the above program, note how the array elements are accessed. The variable numlist is used as a pointer that points to the first element of the array.
 
Pointer variable Memory Address Contents of memory (Array elements)
numlist[0]
333000
*numlist[0] = 9
numlist[1]
333002
*numlist[1] = 7
numlist[2]
333004
*numlist[2] = 8
numlist[3]
333006
*numlist[3] = 7
numlist[4]
333008
*numlist[4] = 7
numlist[5]
333010
*numlist[5] = 9
numlist[6]
333012
*numlist[6] = 1
numlist[7]
333014
*numlist[7] = 6

One problem with the kinds of arrays we have used until now is that we must specify the size of the array when we write the program.   This may cause two different problems; 1) we may create an array much larger than needed, 2) we may create one that is smaller than what is needed.  In general, this problem is created because we don't know the size of the array until the program is run. This is where dynamic arrays are used. The new expression can be used to allocate an array on the freestore.Since array variables are pointer variables you can use the new operator to create dynamic variables that are arrays, and then treat these dynamic array variables as if they were ordinary arrays. Recall program P10_1b.cc from lab 7. It is reproduced here below

// P10_1b.cc - 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;

}

Note that SIZE was defined as a const int. Now lets modify this program and re-write it creating the array dynamically.

// P12_2a.cc. Illustrates dynamic arrays
#include <iostream>
using namespace std;

int main(void)
{
   int SIZE;
   cout<<"Enter the size of the array"<<endl;
   cin>>SIZE;

    int *numlist = new int[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!
    }
   delete[] numlist;
   return 0;
}

Note how the array numlist has been declared dynamically using the new operator to construct an array of the required size in the freestore. This freestore memory is not automatically freed once the array is no longer needed, or goes out of scope. In an efficient program, we will take as much memory as we need and then free it up when we are done with it. We need to use the delete operator to do this.
Notice the empty square brackets when the delete operator is used on the pointer variable numlist. This ensures that the memory occupied by every element of the array pointed to by numlist - and not just the first element! - is removed and the space it occupied re-allocated.

Display 12.5 in the textbook lists a program that uses dynamic arrays to sort a list of numbers entered at the keyboard.

A dynamic array can have a base type which is a struct. You can use the base type struct just as you would use a predefined data type integer or float.

Exercise 12.2
Define a struct Student that has as its members the student_name and a student_ idnumber both of type string. Input from the keyboard the number of students in the database, then create a dynamic array of type Student and input the information for each student. Once you populate the database (store all information), display the entire database. Remember to delete the dynamic array pointer before exiting the program.


back to part 2