Introduction to C++ Arrays

An array in C++ consists of a set of objects (called its elements), all of which are of the same type and are arranged contiguously in memory. Arrays provide a convenient way to manipulate store large amounts of data from within programs. Arrays allows for setting aside a group of memory locations which we can then manipulate as a single entity, at the same time enabling us direct access to any individual component.

All elements of the array are grouped under one symbolic name or identifier. All elements are positioned next to one another in the memory and are indexed in the order they are arranged beginning from position zero. The index of each element is used to access that element. The number of elements in an array is called its dimension. The dimension of an array is fixed and predetermined, it cannot be changed during program execution.

An array in C++ is declared as follows
DataType  ArrayIdentifier [NumberOfElements]
Suppose we want to store the grades of 10 students in a class. We can declare and initialise grades array as follows
int grades[10]={35,60,55,50,65,80,70,75,45,85}
we can diagrammatically represent arraygrades as follows;


To access each of the elements of the grades array, we write the name of the array followed by the index of the element enclosed in square brackets as indicated below;

grades[0]=35   grades[1]=60 ……………hours[4]=65…………….hours[9]=85 
We can actually add, subtract and divide the values or elements of the array in order of our choosing. See examples below

grades[1]+ hours[4]= 60 + 65=125  grades[6]/grades[0]=70/35=2

 grades[9]-grades[3]=90-50=40 
We can also include also do arithmetic with the subscripts themselves. An expression within the square brackets can be evaluated to determine the actual subscript. For example we could write grades[3] as;

grades[1+2] or grades[8-5] or 
 
 if a=grades[2]   and   b=grades[6]  then 

 grades[3]=grades[(a+b)/50]

Note that the square brackets [] are actually an operator with the same level of precedence as parentheses. Note also that in grades[3] subscript or index 3 refers to the fourth element of the array and not array element three. Array element three has the index of 2.


Arrays are used to store data which consist of individual items but of the same type, i.e. a list of names, a table of world cities and their zip codes, or list bank clients and their monthly banck account transactions.


An ‘index out of bounds’ runtime error occurs in case of an attempt to access a non-existent array element (i.e an element outside the indexes like grades[-1] or grades[10])


Initialising and Processing Arrays

Arrays can be initiated either by loops or by the initialisation list. The later is mainly used once to initialise the array while the former can be used even at any stage during the program flow. In the example below we initialise the arrays grades[] and DivGradesBy2 using both techniques. Subscript expression is used to determine the value of grades[3] and the for loop statement to display the indexes and elements of the grades array

#include>iostrem>
 using namespace std;

 int main()
 {
   int grades[10]={35,60,55,50,65,80,70,75,45,85}; //initializing grades[]using the initialization list

  int a=grades[5];
  int b=grades[6];
  int DivGradesBy2[10]={}; //DivGradesBy2[] is initialized to zero
    for (int i=0; i<10; i++)
 
  {

  //for loop modifies DivGradesBy2[] by inserting grades' elements that      //are divisible by 2 

   if(grades[i]%2==0)
   DivGradesBy2[i]=grades[i];   
                                  
  }
  cout<<"The va;lue of grades[3] is "<<grades[(a+b)/50]<<endl;
  cout<<endl;

  cout<<"Index Number"<<setw(12)<<"Grades"<<setw(18)<<"GradesDivBy2"
         <<endl;
  for (int i=0; i<10; i++)
       cout<<setw(6)<<i<<setw(18)<<grades[i]<<setw(13)<<DivGradesBy2[i]<<endl;
 
  return 0;
 }
Output:
The va;lue of grades[3] is 50

 Index Number       Grades      GradesDivBy2
      0                35            0
      1                60           60
      2                55            0
      3                50           50
      4                65            0
      5                80           80
      6                70           70
      7                75            0
      8                45            0
      9                85            0

Note the way we initialised DivGradesBy2[10]={}, this is another way of initializing An array in C++ with default values of zero. Actually if you declare an array and initialize it with less than its size, the compiler will initialize all the rest with zero. So by stating DivGradesBy2[10]={},we imply that all elements are zero since we included less than (actually nothing) ten elements in the initialization list. setw() is used to set the field width in which the next value will be output.


Adding elements of the Array

We can also use the loop to sum up the elements of the array. The example below sums up the elements of our grades array

#include>iostrem>
 using namespace std;

 int main()
 {
  int grades[10]={35,60,55,50,65,80,70,75,45,85}; //initializing using the initialization list
  int TotalGrades=0; 
  for(int i=0; i<10;i++)
  TotalGrades+=grades[i];

  cout<<"The total in the grades array is "<<TotalGrades<<endl;

  return 0;
 }
Output:
The total in the grades array is 620

Counting and tallying Array Elements

It is possible to count the elements of the array and display thier frequency in a graph form. The program below does just that

#include>iostrem>
 using namespace std;

 int main()
 {
  int grades[12]={10,20,30,30,50,60,50,70,40,80,90,100}; //initializing using the initialization list
  int gradeCount[11]={}; //initializing gradeCount to zero
 for(int count=0; count<12; count++)
  gradeCount[grades[count]/10]++;          // count elements in grades that are the same

  cout<<" Range   Distribution"<<endl; 

 for(int i=0; i<10;i++)
  {
 
    if(i<=0)
  cout<<" 0-10%: ";

  else if(i==9)
  cout<<"  100%: ";

  else
  cout<<i*10<<"-"<<i*10+1<<"%: ";

 for (int c=0; c<gradeCount[i]; c++)
  cout<<setw(4)<<"*";
  cout<<endl;
 }
 return 0;
 }
Output:
Range   Distribution
  0-10%: 
 10-11%:  *
 20-21%:  *
 30-31%:  * *
 40-41%:  *
 50-51%:  * *
 60-61%:  *
 70-71%:  *
 80-81%:  *
   100%:  *
First we summarise the elements of grades array into gradeCount array. To achieve this we enter each the values of grades as subscripts of countGrades. The grades array values are divided by ten so as to get the values between 1 and 10. The values evaluated from grades[count]/10 become subscripts for countGrades array which we increment by one. For example when cout=0 grades[count]=10 and so 10/10=1. This result is entered as a subscript for countGrades array as in countGrades[1] whose value is then incremented by one. The loop ensures that same logic is done for all grade array values.
When the process is done, countGrades will be containing the number of times each element appears in the grades array. We display this frequency using the for nested loop. The nested loop prints range and distribution of the grades.Note the way we used “if statement” to print out the range. Note also the way we printed graphical representation of countGrades using the nested “for loop” . The value for the loop continuation condition we used in inner loop is c<coutGrade[i]. This helps determine the number of * to print.

Sorting Arrays with Insertion Sort

Insertion sort helps us arrange array in a sorted manner. The insertion sort compares the first two elements and swaps them if one is greater than the other. It then compares the third elements with the first two and then inserts it in an appropriate position. The process goes on like that through i=n iterations where all elements have been sorted. To table below illustrates the process of insertion sort.
We use a for loop statement to iterate through the array. We also use a temporally variable to store the current value at each iteration. The loop terminates either when the program reaches the reaches the last element or when it reaches a value that is less than the one to be inserted. The algorithm of the insertion sort is easy but can be inefficient with large arrays. Follow the example below;
#include>iostrem>
using namespace std;

int main()
{
  const int size=10;
  int putValue;  
  cout<<"The elements of grades array before sorting are ";
  int grades[size]={8,2,10,4,5,9,7,1,6,3};
 for (int j=0; j<size; j++)
  cout<<grades[j]<<" ";
  cout<<endl;
 for(int i=1; i<size; i++)
  {
    putValue=grades[i];   //Temporally variable to stores current value at each iteration 

// while the element in (i-1) position is great than that in i position and the index for each element is greater than zero, swap them, move to next     
while((i>0) &&(grades[i-1]>putValue)) 
  {
   grades[i]=grades[i-1];
   i--;
  }

   grades[i]=putValue;
   }
  cout<<"The elements of grades array after sorting are ";
 for (int j=0; j<size; j++)
  cout<<grades[j]<<" ";
 
  return 0;
 }
Output:
The elements of grades array before sorting are 8 2 10 4 5 9 7 1 6 3 
The elements of grades array after sorting are 1 2 3 4 5 6 7 8 9 10 

Searching Array with Linear Search

A Linear Search enables us to search the array to determine whether it contains a value of our choiceUsing a search key, the linear search compares its value with each element of the array to determine whether they are the same. . After the search, the program should indicate to us that the value has been found or not found. Follow the example below;
#include>iostrem>
using namespace std;

int main()
{
 const int size=10;

 int grades[size]={1,2,3,4,5,6,7,8,9,10};

 int key=6;    //The value to search for in array grades 
 int KeyFound=-1;  //Control value in case the key is not found 
 int value=0;   //The value=key found in the array 
    for(int i=0; i<size; i++)
       {
    if(grades[i]==key) // if the key is found 
     {
      KeyFound=i;  // Store its index in the control value 
  value=grades[i]; //Store the value for future use
      }
        }
  if(KeyFound!=-1)// if the key has been found 
cout<<"The Key value of "<< value<<" has been found in      element "<<KeyFound;
 else
    cout<<"The Key was not found in element ";

 return 0;
}
Output:
The Key value of 6 has been found in element 5

Passing Arrays to Functions

Arrays can be passed as parameters to functions so as to maintain a structured design. A data type followed by the array square brackets symbols [] are passed as a parameter to indicate that the function will receive an array. The array length is also passed to a function as a second parameter. The calling function will only include the name of the array and its length. The square brackets are not included in the calling function. Remember the name of An array in C++ is itself a pointer (i.e. it keeps the address) to the first element of the array. For this reason, there is no need to include the address reference symbol (&) on the name of the array. In other words, the action of entering an array name as an argument effectively references parameters (i.e. passes the address rather than value parameters). Because of this, it is the address but not copies of the array that is passed to the function. This enables the function to access the elements of the array and where appropriate perform any modifications. Follow the example below which uses the insert sort technic in a function
#include>iostrem>
 using namespace std;

 void sortGrades(int arr[],int length)
 {
  int insert;
  int next;
 for (int i=1; i<length; i++)
 {
  insert=arr[i];  // at each iteration on a temporally basis store the corresponding element 
  next=i;

 // while the element in “next-1” position is great than that in “next” position and the index (next) is greater than zero, swap elements and move to next    
 
 while((next>0)&& (arr[next-1]>insert))
 {
  arr[next]=arr[next-1];
  next--;
 }
  arr[next]=insert;  //insert the swapped element into the array
 }
 }
 
 int main()
 {
  cout<<"Before sorting, the elements of the grades array are ";
 
  const int size=10;
  int grades[size]={20,35,40,70,80,90,65,50,95,100};

 for(int j=0; j<size; j++)
  cout<<grades[j]<<" ";
  cout<<endl;
  sortGrades(grades,size);   // Only the name of the array has been entered 

  cout<<"After sorting, the elements of the grades array are ";

 for(int j=0; j<size; j++)
  cout<<grades[j]<<" ";

  return 0;
 }
Output:
Before sorting, the elements of the grades array are 20 35 40 70 80 90 65 50 95 100 
After sorting, the elements of the grades array are 20 35 40 50 65 70 80 90 95 100 

C++ Multidimensional Arrays

In c++ an array can have more than one dimension. It can have two or three, or more dimensions even though the arrangement of its elements in memory remains same as that of a one dimensional array (i.e. elements are stored in a contiguous sequence). Although the elements of a multi-dimensional array are organised contiguously in memory, we perceive the elements in a table form as indicated in the table below. Suppose we have four students whose grades of maths physics and chemistry in the array grades. The table below shows how we would show their respective grades.
StanleyHenryAnneSilvaMolly
Maths3545607035
Physics6525758045
Chemistry5050707530

In arrays language, the above table is said to be a two (rows) by two (columns) dimensional array. Because it contains three rows and five columns, we declare this two-dimensional array as follows
int grades[3][5];
In reality however the elements of the array grades a stored in memory in a consecutive manner similar to that of a one dimensional array. Grades representing Maths are listed first followed by those of Physics and lastly of Chemistry. The figure below mirrors how the grades array are stored in memory.



Labels are only included to match the scores with subjects and the students. Otherwise the idea is to show how the data is organised in memory. As you can see array elements are stored in a consecutive manner whether they are of a single or a multi-dimensional array.  As said earlier the table concept is for (programmers or users) conceptual visualisation. 

 

Initializing and Accessing a Multi-Dimensional Array

In c++ multi-dimensional arrays are initialised and accessed in a similar manner like the single dimensional array. However, a few differences exit. As you may have noticed, we used two pairs of square brackets to represent a two by two dimensional array. Thus when initialising or accessing a multi-dimensional array the respective brackets and subscripts or indexes should be included. Note also that the number of the elements of the array is exactly the product of the two subscripts of the array(i.e. 3 x 5 =15).
Like we did with a single array, we can initialise a multidimensional array using either a initializer list or a loop. Below we initialise our grades array with an initializer list.

int grades[3][5]={ 35,45,60,70,35,65,25,75,80,45,50,50,70,75,30};

We can also include nested braces (which actually is a best way) at each set of numbers representing a row (or a subject in our case) as follows

int grades[3][5]=  { {35,45,60,70,35},
                     {65,25,75,80,45},
                     {50,50,70,75,30}
                   };
The nested initializer is preferred because it more informative and versatile. With a nested initialiser we can initialize only the first element of each row and have the rest default to zero:
int grades[3][5] = {{35}, {65}, {50}};
Or we can omit the first dimension as long as subsequent dimensions are included and let the other be derived from the initializer: For example

int grades[][5]=  {  {35,45,60,70,35},
                     {65,25,75,80,45},
                     {50,50,70,75,30}
                  };

A loop statement is used to initialise the a multi-dimensional array in the same way we did with a one dimensional array. For example;

#include>iostrem>
using namespace std;

  const int row=3;
  const int col=5; 
  int length=row*col;
  void initialGrades(int [][col],int);
 int main()
 {

  int grades[row][col]={};
 for (int i=0; i<row; i++)
 for(int j=0; j<col; j++)
 grades[i][j]=(10*(i+1))+(10*(j+1));
 cout<<"The elements of grades array are \n";

 initialGrades(grades,length);

 return 0;
 }

  void initialGrades(int arr[][col],int length)  //only the column is passed 
 {
 for (int i=0; i<row; i++) // the first loop of the two necessary to access the elements of a two dimensional array
 {
 for(int j=0; j<col; j++) //second loop 
 {
  cout<<arr[i][j]<<" ";  //
    if((i==0 &&j==4) ||(i==1 &&j==4)||(i==2 && j==4))
  cout<<endl;
 }
 }
 }
Output:
The elements of grades array are 
20 30 40 50 60 
30 40 50 60 70 
40 50 60 70 80

As you might have noticed we used two loops to access the elements of a two dimensional array. This is important to remember, when dealing multi-dimensional arrays. The number of dimensions will determine the number of the loops when accessing the elements an array. You can also observe that 2nd dimension was explicitly in the function call. This also important to remember that for an array of two or more dimensions, all the dimensions symbols (i.e. [] ) have to be passed to a function. Note also how we passed to a function only number of columns and not the rows. All that the function needs to know is the number of columns in the array, the rows are automatically derived.

Vectors

A vector in c++ is an object that contains a sequence of other objects but all of which must all taking up the same amount of storage. Vectors are used mainly in situations where there is a sequence of similar items to be stored and accessed by their sequence numbers. Vectors are held in a special library and can be used by including the vector header in the program as in
#include  

Like arrays a vector is numbered starting with zero 0 and a call to it follows similar array notations. For example if we consider our grades to be a vector then a call to the vector grades could be written as grades[0], grades[1], grades[2] …until grades [n-1], where n is the number of elements in the vector.

Unlike arrays whose elements are fixed, new elements can be "pushed" onto the end or "popped" off of a vector. In other words a vector can either reduce or increase in size. Vectors are empty by default on creation and thus an is empty ( grades.empty) check returns true. However it is an error to call a vector ( i.e. grades [i]) if it is empty. Vectors should be passed by reference whenever possible.
When declaring we write a vector key word followed by its type (i.e. int, float, double, or the name of a class) enclosed in angle brackets, followed by the name of the vector and the number of elements in the vector as follows ;

vector<T> grades(numberOfItmes);  // where T is a type 
  Or we can leave out the number of items and declare it as 

  vector<T> grades;

Any of the above statements declare a new and empty vector called grades. With this declaration we can do any of the following we, declare a new and empty vector called grades. With this declaration we can do any of the following we ;
  • Test to see if grades is empty using the:
    grades.empty();
  • Find the number items in grades using the :
    grades.size();
  • Determine the length of the string in the vector ( if grades is a string) using:
    grades.lenght(); 
  • Push t in T onto the end of grades using the :
    grades.push_back(t);
  • Pop the back of grades off grade using the :
    grades.pop_back();
  • Access the ith item of grades without checking if it exists using :
    0<=i<size() and grade[i];
  • Assign a copy of another vector say grades2 to grades as in:
    grades = grades2;
In the example below we assume we do know the number of the grades and so we declare the vector first and enter in the number at the time we get to know. Using the for loop we initialise the vector grades, assign it to vectors scores and marks, push back into grades and pop back off scores. At each stage we print the results. At the end we compare vector marks with grades to check whether they are equal, we print the results of the comparison.


#include>iostrem>
     using namespace std;

 int main()
 {
  vector grades;
  vector scores;

  const int size=10;

  grades.resize(size);
  cout<<"The alements of the vector grades are ";
 for(int i=0; i<size; i++)
 {
   if (i==0)
  grades[i]=5;
   else
  grades[i]=i*10;

   cout<<grades[i]<<" ";
 }
  cout<<endl;

  vector marks(grades);    //copying elments of grades into mark using the copy constructor 

  cout<<"vector marks now contains element of grades, which are "; 
 for(int i=0; i<size; i++)
 {
   cout<<marks[i]<<" ";
 }
  cout<<endl;

  int moreGrades=100;
  grades.push_back(moreGrades);  // push additional items at the end of vector 'grades'
 
  const int newSize=grades.size();  //Determine the new size
  cout<<"After adding a new element, items are "; 
 for(int i=0; i<newSize; i++)
 {
   cout<<grades[i]<<" ";
 }

  cout<<endl;

   scores=grades;    //Copy elments of grades into vector scores

  cout<<"vector scores now contains element of grades, which are "; 

 for(int i=0; i<newSize; i++)
 {
   cout<<scores[i]<<" ";
 }
  cout<<endl;

  scores.pop_back();     // remove the element we just added
  cout<<"The new item (100) in vector 'scores' is removed, now the items are "; 

 for(int i=0; i<newSize-1; i++)
 {
   cout<<scores[i]<<" ";
 }
  cout<<endl;
   if (marks!=grades)   // check whether scores is equal to grades
  cout<<"vector 'marks' is not equal to vector 'grades' ";
   else 
  cout<<"marks and grades are equal";
  
  return 0;
 }
Output:
The alements of the vector grades are 5 10 20 30 40 50 60 70 80 90 
vector marks now contains element of grades, which are 5 10 20 30 40 50 60 70 80 90 
After adding a new element, items are 5 10 20 30 40 50 60 70 80 90 100 
vector scores now contains element of grades, which are 5 10 20 30 40 50 60 70 80 90 100 
The new item (100) in vector 'scores' is removed, now the items are 5 10 20 30 40 50 60 70 80 90 
vector 'marks' is not equal to vector 'grades' 
PREV:Introduction to Pointers NEXT:Introduction to Structures