Arrays (1)
Almost like a list
in Python and are
used to store multiple items in a single variable
However, slightly different as they store only a
single type of data
i.e. double, boolean or integer
They are considered to be:
ordered : the items have a defined
order, and this order will not change when new items are
added to the array
changeable : the items of an array
are mutable (can be changed), added or removed
allowable of duplicates : arrays are
indexed, and therefore items in an array can be
duplicated
You will be aware from your first year programming
module, that a variable will only hold a single value of
a particular data type, and this is true for C++ as
well. However, just as we can in Python use lists to
store multiple values in a single variable, we can also
achieve this in C++ in the form of an array.
Arrays are just like a list in Python and can be used
to store multiple values. However, they work slightly
different, and can only store data for a single type of
data, i.e., integer, double, floats or strings. Arrays,
just like lists, are considered to be ordered,
changeable and allowable of duplicates. I shall go
through each one of these and explain what this means to
remind you.
When we say an array is ordered, it is meant that the
items have a defined order, and this order will not
change. For example, when an array is initially
constructed, a value would have been placed at a
particular position (or index). Over the course of
developing your script or application, you may want to
add another item to the array. When adding another item
to the array, the order in which the items have been
stored does not change. As such, any array in C++ is
considered to be ordered .
Arrays are also considered to be mutable, which, in
essence, means that we change them by adding or removing
values. Additionally, we can also move the items around
by using algorithms known as sorting
algorithms . You should recall being taught sorting
algorithms in your first year programming module. If you
do not remember this, you may want to revisit the
lecture material from that module.
Arrays are also able to store multiple items of the
same value, and this is because they are indexed. To
access a particular item of an array, the index number
is used.
Arrays (2)
Creating an Array
Arrays are declared by using a set of square
brackets ([]
) at the end of the variable
name
Inside the set of square brackets will be a number
indicates the number of elements that can be stored
in the array
dataType arrayName[arraySize];
The items inside the array can only be of the data
type that was assigned to the variable
int intArrayExample1[10]; // Stores only integers
double dblArrayExample1[3]; // Stores only doubles
char charArrayExample1[26]; // Stores only characters
When it comes to creating an array in C++, this can
be achieved by using the square brackets notation
appended to the end of the variable name. Inside these
square brackets will be an integer number, and this will
denote the number of elements (or items) that can be
stored in the array.
It is important to remember that when we create our
variables in C++, we must specify the data type before
the variable name is given. Unfortunately, in C++, this
will limit the values that can be stored in the array to
that particular data type.
On the screen, you will see three examples of
declaring an array for each of the following data types:
integer, double, and character. You will see that for
each of these examples I have specified the data type at
the beginning, followed by a variable name, with a set
of square brackets appended to the end. Inside these
square brackets, I have provided an integer value to
specify how many items I wish to store in that
array.
Let’s have a closer look at the first example,
intArrayExample1
. For this variable, as the
name suggests, we want to store integer numbers inside
it. Therefore, we begin with defining the data type of
our variable. In this case, we know that we want to
store integers, therefore, we use the int
keyword, followed by the name of our variable. We now
need to specify the number of values we wish to store
inside our array. At this moment in time, I know I want
to store ten values inside my array, and as such, I
append a set of square brackets to the end of my array
name and provide integer value 10.
What this will do is it will reserve enough memory on
the machine to store ten integer values. However, it
will not allow us to store eleven values or more, and I
will discuss later on how we can increase the size of
our array to store more than ten values later on in this
lecture.
Arrays (3)
Initialising an
Array
Array can be populated by using the curly braces
({}
) after the variable name
declaration
int intArrayExample1[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
double dblArrayExample1[3] = {1.0, 2.0, 3.0};
char charArrayExample1[26] = {'a', 'b', 'c', 'd', 'e'};
On the previous slide, I discussed the process in
which you would follow to create an array.
However, you may recall from your Python classes that
lists can be pre-populated on their initial creation.
This can also be achieved in C++ and is known as
initialisation .
Similar to the process of creating an array, however,
after we have provided the size of our array in square
brackets, we can use the assignment operator (the equal
character) to assign some values to the array. You will
notice on the screen the same three arrays from the
previous slide. However, this time I am assigning some
values on the arrays’ creation. This is achieved using a
set of curly braces after the assignment character.
Inside the curly braces, we can then provide some
values (of the corresponding data type for that array)
that we wish to store. In the
charArrayExample1
variable, we can see that
we initially created the array to store twenty-six
values. We then provide our assignment character,
followed by a set of curly braces. Inside the curly
braces, we provide some values of the char
data type. You should recall from last week’s lecture
that a character is stored using single quotes and a
single value. In this case, the first element of our
array is the letter a
in lower-case. We can
provide a further element by using a colon and providing
another character in single quotes.
In this example, we can see that for our
charArrayExample1
we are storing the
characters, a
, b
,
c
, d
and e
.
However, we have not provided the full number of
characters for our array. If you recall, we created our
array to store twenty-six characters, but in this case I
have only provided five characters. Therefore, we still
have room for a further twenty-one characters.
Arrays (4)
Accessing an Arrays
Element
The items in an array can be accessed by referring
to its index number inside a set of square brackets
([]
)
remember that the index of an array begins
at 0
in C++
int arrayExample11[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
#include <iostream>
int arrayExample11[ 10 ] = { 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 };
int main() {
std:: cout << "arrayExample11[0] -> " << arrayExample11[ 0 ] << std:: endl;
std:: cout << "arrayExample11[3] -> " << arrayExample11[ 3 ] << std:: endl;
std:: cout << "arrayExample11[9] -> " << arrayExample11[ 9 ] << std:: endl;
return 0 ;
}
arrayExample11[0] -> 10
arrayExample11[3] -> 7
arrayExample11[9] -> 1
Accessing an element of an array are very similar to
the process you would have been taught for Python.
Essentially, we need to call the name of our variable
that holds an array, and place a set of square brackets
at the end. Inside the set of square brackets we provide
an index number in order to access that element.
It is important to remember that just like Python,
arrays in C++ begin at index zero and
not one. On the screen, you will see an
example of an array that holds ten integer numbers. In
the blue box, you will also see that I am accessing the
variables that are stored at indices, zero, three, and
nine, respectively. Each of these indices returns the
corresponding integer that is stored at that index. For
example, index zero returns ten and index nine returns
one.
Arrays (5)
Getting the Size
of an Array i
There is no in-built function to obtain the size
unlike a Python list
Could use the sizeof()
function to find
the array size
int arrayExample11[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
sizeof(arrayExample11);
#include <iostream>
int arrayExample11[ 10 ] = { 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 };
int main() {
std:: cout << "sizeof(arrayExample11) -> " << sizeof ( arrayExample11) << std:: endl;
return 0 ;
}
sizeof(arrayExample11) -> 40
The above code returns 40 as the size of the
array
The sizeof()
function returns the size
of the data type in bytes
as we have 10 integers, and each integer occupies 4
bytes of memory, 40 is returned
Unlike Python, there is no in-built method of
returning the size of an array. There are some functions
available, for example, the sizeof
function. However, as you can see from the example on
the screen, the function does not exactly return the
true size of an array.
You will see, that when we call the
sizeof
function on
arrayExample11
the value forty is returned.
This is because the function returns the size of the
data type in the form of bytes. In this instance, our
array is storing ten integers. In the C++ programming
language, each integer occupies four bytes of space in
the memory. Therefore, when four is multiplied by ten,
we get forty bytes. This would explain why the
sizeof
function returns value forty.
But this is not particularly useful. When we say we
want to get the size of an array, we mean how
values are stored within it. Therefore, we need to do
some extra calculations in order to get this number.
Arrays (6)
Getting the
Size of an Array ii
Therefore, if we know the size of the data type,
then a simple calculation can return the array size
int arrayExample1[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
sizeof(arrayExample1) / sizeof(int);
#include <iostream>
int arrayExample1[ 10 ] = { 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 };
int main() {
std:: cout << "sizeof(arrayExample1) / sizeof(int) ≈ " << "40 / 4" << std:: endl;
std:: cout << "sizeof(arrayExample1) / sizeof(int) -> " << sizeof ( arrayExample1) / sizeof ( int ) << std:: endl;
return 0 ;
}
sizeof(arrayExample1) / sizeof(int) ≈ 40 / 4
sizeof(arrayExample1) / sizeof(int) -> 10
Which leads me nicely onto the process of how we can
retrieve the number of elements in an array. On the
screen, you will see some code on how this value can be
calculated.
You will see that we are making good use of that
sizeof
function in order to calculate the
length of our array. To achieve this, we apply the
function on the variable name of our array, and then we
do a division on that number by the size of an
int
.
As I have previously explained, we know that the size
of our array is forty, and that an integer occupies four
bytes of memory. Therefore, in this instance, our
division calculation is going to be:
40 / 4
. The outcome of this equation can be
seen on the screen where the value ten is returned.
We can see that by eyeballing our array declaration
on the screen that there are indeed ten numbers present
in our array, and as such, we have now found our
length.
Arrays (7)
Inserting
Elements into an Array i
The elements in an array are
ordered and indexed ,
therefore modifiable
otherwise known as being mutable
Items can be inserted into the array by calling an
index number that has not been populated at initial
creation
int arrayExample1[8] = {10, 9, 8, 7, 6};
arrayExample1[6] = -9;
#include <iostream>
int arrayExample1[ 8 ] = { 10 , 9 , 8 , 7 , 6 };
int main() {
arrayExample1[ 6 ] = - 9 ; // Let's insert a new element
for ( int i = 0 ; i < ( sizeof ( arrayExample1) / sizeof ( int )); i++) {
std:: cout << "arrayExample1[" << i << "] -> " << arrayExample1[ i] << std:: endl;
}
return 0 ;
}
arrayExample1[0] -> 10
arrayExample1[1] -> 9
arrayExample1[2] -> 8
arrayExample1[3] -> 7
arrayExample1[4] -> 6
arrayExample1[5] -> 0
arrayExample1[6] -> -9
arrayExample1[7] -> 0
The next example we shall be looking at is the
process of inserting an element into an array. Due to
the properties of arrays in the C++ programming
language, whereby they are ordered and indexed, this
means they can be modified. Items can easily be inserted
into an array by calling an index number that has not
been populated when it was initially created.
For example, on the screen we have our variable
arrayExample1
which has been created to
reserve eight blocks of memory. However, you will see
from our initialisation that we have only populated the
first five indices with the values: 10
,
9
, 8
, 7
, and
6
. Therefore, the next three indices will
be populated with a zero to reserve the memory.
In order to insert an element into our array, we can
use the square brackets. These will append to the end of
our variable name and populated with an integer. This
integer would be the index in which we want to insert
our new element. In this case, I have decided to insert
an element at index six, and in this case I want to
store minus nine.
You will see in the blue box on the screen that when
I access each index of the array and display it to the
screen, the stored value is returned. You will see that
indices five and seven have been populated with the
value zero. This is because the C++ compiler has
populated these indices with zero to reserve the memory.
However, you will see for index six that the value
-9
has been inserted.
Arrays (8)
Inserting
Elements into an Array ii
Elements at a particular index can also be
replaced
Achieve by accessing the index of the element you
wish to replace
int arrayExample1[8] = {10, 9, 8, 7, 6};
arrayExample1[2] = -9;
#include <iostream>
int arrayExample1[ 8 ] = { 10 , 9 , 8 , 7 , 6 };
int main() {
std:: cout << "[Before] arrayExample1[2] -> " << arrayExample1[ 2 ] << std:: endl;
arrayExample1[ 2 ] = - 9 ; // Let's insert a new element
std:: cout << "[After] arrayExample1[2] -> " << arrayExample1[ 2 ] << std:: endl;
return 0 ;
}
[Before] arrayExample1[2] -> 8
[After] arrayExample1[2] -> -9
Similar to the previous slide, the elements for a
particular index can also be replaced. On the screen is
the same example as the previous slide, but instead of
populating index six with a new element, we are instead
going to be replacing the value of an index that has
already been populated.
In order to achieve this, we can use the square
bracket notation as earlier. However, this time we
change the index of the element that we wish to
populate. In this example, I am changing index two which
stores value eight, to now store value nine.
As you can see from our output on the screen, the
value has been changed.
Arrays (9)
Resizing an Array
A disadvantage to using an array is the static size
construction
e.g. int arrayExample1[10]
can only
store ten integers and no more
A method of resizing an array is to create an array
of a new size and copy the contents from the old
array
int arrayExample1[8] = {10, 9, 8, 7, 6, 5, 4, 3};
int arrayExample2[15];
int main() {
for(int i = 0; i < (sizeof(arrayExample1) / sizeof(int)); i++) {
arrayExample2[i] = arrayExample1[i];
}
return 0;
}
#include <iostream>
int arrayExample1[ 8 ] = { 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 };
int arrayExample2[ 15 ];
int main() {
for ( int i = 0 ; i < ( sizeof ( arrayExample1) / sizeof ( int )); i++) {
arrayExample2[ i] = arrayExample1[ i];
}
for ( int i = 0 ; i < ( sizeof ( arrayExample2) / sizeof ( int )); i++) {
std:: cout << "arrayExample2[" << i << "] -> " << arrayExample2[ i] << std:: endl;
}
return 0 ;
}
arrayExample2[0] -> 10
arrayExample2[1] -> 9
arrayExample2[2] -> 8
arrayExample2[3] -> 7
arrayExample2[4] -> 6
arrayExample2[5] -> 5
arrayExample2[6] -> 4
arrayExample2[7] -> 3
arrayExample2[8] -> 0
arrayExample2[9] -> 0
arrayExample2[10] -> 0
arrayExample2[11] -> 0
arrayExample2[12] -> 0
arrayExample2[13] -> 0
arrayExample2[14] -> 0
A downside to using arrays is the static
construction, whereby once you have stated the size of
the array it cannot be changed. This is particularly
poor, as you are required to know in advanced how many
values you wish to store in the array. Unlike Python,
where you can continuously keep adding to the list, this
is not the case in C++. Therefore, in order to adjust
the size of an array we need, write some
questionable code.
In this example, we have our array from previous
slide, arrayExample1
, which stores the
values ranging from ten to one. If we were to add more
integers to this array, then when the script is executed
it would forcibly quit with an interruption fault. This
is because you are attempting to access the index of the
array that does not exist and has not been reserved in
the memory. Therefore, when the compiler attempts to
access the memory address to add the new value, an error
occurs and the script stops executing.
Therefore, we need to think about how to extend our
array, and in order to do this, we need to create a new
array declaration and set the new size of this array. As
you can see from the example on the screen, we have
created a new variable called arrayExample2
which has been initialised with value fifteen. This
instructs our compiler to create an array and reserve
fifteen blocks of memory to store our elements in.
We then need to use a method of copying our values
that are already stored in arrayExample1
into our newly created array. To aid us in doing this,
we could use a for
loop. Do not be too
concerned about the structure of the for
loop as we shall be looking at this in a lecture next
week. However, the important part to take from this is
the part where we are copying the contents from
arrayExample1
to
arrayExample2
. Once the contents of our
array have copied over, the remaining blocks of memory
in our new array will be filled with a zero in order to
reserve the memory address for later use.
As you can see, this is really not an intuitive
method of increasing the size of the array. We must
always declare a manual number for the size of our
array, which means that when arrayExample2
fills up, we need to repeat the process of copying our
elements across to our “new” array and so on. There is a
better method for storing multiple values in a single
variable, and we shall look at this very shortly in the
lecture.
Arrays (10)
Removing Elements from an Array
Removing requires using a searching algorithm to
find the element and remove it
You must declare the target
value to be
removed
Searching for the
Element
int arrayExample1[8] = {10, 9, 8, 7, 6, 5, 4, 3};
int target = 5; // Element to be removed
int i;
for(i = 0; i < (sizeof(arrayExample1) / sizeof(int)); i++) {
if(arrayExample1[i] == target) {
break;
}
}
Removing the Element
if (i < (sizeof(arrayExample1) / sizeof(int))) {
// Adjust the size of the array search
n = (sizeof(arrayExample1) / sizeof(int)) - 1;
// Shift our elements from the right of our found target
for(int j = i; j < n; j++) {
arrayExample1[j] = arrayExample1[j + 1];
}
}
#include <iostream>
int arrayExample1[ 8 ] = { 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 };
int target = 5 ;
int i, n;
int main() {
for ( i = 0 ; i < ( sizeof ( arrayExample1) / sizeof ( int )); i++) {
if ( arrayExample1[ i] == target) {
break ;
}
}
if ( i < ( sizeof ( arrayExample1) / sizeof ( int ))) {
n = ( sizeof ( arrayExample1) / sizeof ( int )) - 1 ;
for ( int j = i; j < n; j++) {
arrayExample1[ j] = arrayExample1[ j + 1 ];
}
}
for ( int k = 0 ; k < n; k++) {
std:: cout << "arrayExample1[" << k << "] -> " << arrayExample1[ k] << std:: endl;
}
return 0 ;
}
arrayExample1[0] -> 10
arrayExample1[1] -> 9
arrayExample1[2] -> 8
arrayExample1[3] -> 7
arrayExample1[4] -> 6
arrayExample1[5] -> 4
arrayExample1[6] -> 3
Things get a little trickier with arrays when it
comes to removing an element. In order to remove an
element, otherwise known as our target ,
we must search through the array and locate the index it
is located in. On the right-hand-side of the screen, you
will see a collection of code.
The first portion of the code is showing the method
in which we shall be searching our array. You may recall
from the first year programming module that the type of
searching that is being done in this code is linear
search as we are checking each index of our array
sequentially, starting from zero and up to the end of
our list. Once our target element has been found, the
for
loop will be broken out of, and the
index value stored in the variable called
i
.
Once we know the location of our element, we can
begin the process of removing it from the array. Before
we begin, we check whether the returned index is less
than the size of the array. This is always a good safety
check to implement in your own work, because if the
element was not found, then the value of i
would be equal to the length of the array, and if you
did not have this check in place, an error would be
returned.
In this case, we know that the value of
i
will be less than the length of our
array, and we can therefore move on and adjust the size
of our array. This is simply done by declaring a new
variable called n
and storing the length of
our original array, minus one (because we are removing
an element).
We can then begin looping through our array, starting
at the index where we found our variable. We can then
begin shifting the elements from the right of the array
to the left. In essence, we are moving our elements to
the left and overwriting the previously stored element.
In this case, the number five will be replaced by four
and so on.
As you can see from the output in the blue box, we
can see that our target element five has been removed
from the array, or should we say overwritten? You can
see that the elements four and three have been shifted
left by one index. This does not mean our array has
shrunk in size though. Index seven still exists, and it
will contain the original value that was stored in that
index. In this case, index seven would still hold value
three. Therefore, you would want to consider a method of
handling this, so that any values in the “empty” indices
should be zero.
Vectors (1)
Similar to an array in C++ and are used to store
multiple items in a single variable
They store only a single type of data
i.e. double, boolean or integer
However , they can grow in size
dynamically
They are considered to be:
ordered : the items have a defined
order, and this order will not change when new items are
added to the vector
changeable : the items of a vector
are mutable (can be changed), added or removed
allowable of duplicates : vectors
are indexed, and therefore items in a vector can be
duplicated
The vector
library needs to be imported
in order to use them
#include <vector>
Earlier, I said there was a better method of storing
multiple items in a single variable. At that point you
were only introduced to arrays, and you have seen in the
last couple of examples they can be quite difficult when
it comes to inserting or removing elements. A much
better approach would be to use something called
vectors .
Just like an array, vectors can store multiple items
of the same data type; this could be
either an integer, boolean or a double. However, a key
advantage to a vector is that they can grow in size
dynamically . Meaning that we do not have to
create a new array each time we have reached the
upper-limit of the reserved memory locations.
Vectors, just like arrays, are considered to be
ordered, changeable and allowable of duplicates. When we
say that a vector is ordered, it is meant that the items
have a defined order, and this order will not change.
For example, when a vector is initially constructed, a
value would have been placed at a particular position
(or index). Over the course of developing your script or
application, you may want to add another item to the
vector. When adding another item, the order in which the
items have been stored does not change. As such, any
vector in C++ is considered to be
ordered .
Vectors are also considered to be mutable, which, in
essence, means that we change them by adding or removing
values. Additionally, we can also move the items around
by using algorithms known as sorting
algorithms . Finally, vectors are also able to store
multiple items of the same value, and this is because
they are indexed. To access a particular item of a
vector, an index number is used.
Vectors (2)
Creating a Vector
Vectors are created by calling the
vector
data type, followed by a set of
angled brackets (<>
)
Inside the angle brackets the data type being stored
inside the vector is specified
std::vector<dataType> vectorName;
The items inside the vector can only be of the data
type that was assigned to the variable
std::vector<int> intVectorExample1; // Stores only integers
std::vector<double> dblVectorExample1; // Stores only doubles
std::vector<char> charVectorExample1; // Stores only characters
When it comes to creating a vector in C++, this can
be achieved by calling the vector
data
type, followed by a set of angled-brackets. Inside the
angled brackets will be the data type of the elements
that will be stored in the vector. The items that are
stored inside the vector will then be only of that type,
similar to how an array can only hold values of a single
data type.
On the screen, you will see three examples of
declaring a vector for each of the following data types:
integer, double and character. You will see that for
each fo these examples I have specified the data type
vector
at the beginning, followed by a
variable name, with a set of angled-brackets appended to
the end. Inside these angled brackets I have provided
the data type for the elements to be stored inside the
vector.
Let’s have a closer look at the first example,
intVectorExample1
. For this variable, as
the name suggests, we want to store integer numbers
inside it. Therefore, we begin with defining the data
type of our variable. In this case, we know that we want
to store integers, therefore, we use the
int
keyword, followed by the name of our
variable. We now need to specify the number of values we
wish to store inside our array. At this moment in time,
I know I want to store ten values inside my array, and
as such, I append a set of square brackets to the end of
my array name and provide integer value 10.
What this will do is it will reserve enough memory on
the machine to store ten integer values. However, it
will not allow us to store eleven values or more, and I
will discuss later on how we can increase the size of
our array to store more than ten values later on in this
lecture.
Vectors (3)
Initialising a Vector
i
Vectors can be populated by using the curly braces
({}
) after the variable name
declaration
// Initialising List
std::vector<int> intVectorExample1 = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
std::vector<double> dblVectorExample1 = {1.0, 2.0, 3.0, 4.0};
std::vector<char> charVectorExample1 = {'a', 'b', 'c', 'd', 'e'};
// Uniform Initialising
std::vector<int> intVectorExample1 {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
std::vector<double> dblVectorExample1 {1.0, 2.0, 3.0, 4.0};
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
On the previous slide, I discussed the process in
which you would follow to create a vector.
However, just like arrays, vectors can also be
initialised upon creation.
Similar to the process of creating a vector, however,
after we have provided the data type of our vector in
angled-brackets, we can use the assignment operator (the
equals symbol) to assign some values to the vector. You
will notice on the screen the same three vectors from
the previous slide. However, this time I am assigning
some values upon the vector creation. This is achieved
using a set of curly braces after the assignment
character.
Inside the curly braces, we can then provide some
values (of the corresponding data type for that vector)
that we wish to store. In the
dblVectorExample1
variable, we can see that
we initially created the vector to store the data type
double
. We then provide our assignment
character, followed by a set of curly braces, and inside
the curly braces we provide some values of the
double
data type. You should recall from
last week’s lecture that a double is a number with a
decimal point. In this example, we can see that for our
dblVectorExample1
we are storing the
values, 1.0
, 2.0
,
3.0
, and 4.0
.
Vectors can also be initialised in an alternative
method, and this is known as uniform
initialisation . The only difference with this
form is that the assignment operator, the equals
character, has been dropped. This means that after our
variable name has been provided, a set of curly braces
are followed, with the corresponding values within them
that we wish to store in the vector.
Vectors (4)
Initialising a Vector
ii
Alternatively, vectors can be created by declaring
an initial size and a default value
std::vector<int> intVectorExample1(5, 0);
#include <iostream>
#include <vector>
std:: vector< int > intVectorExample1( 5 , 0 );
int main() {
for ( int i = 0 ; i < intVectorExample1. size(); i++) {
std:: cout << "intVectorExample1[" << i << "] -> " << intVectorExample1[ i] << std:: endl;
}
return 0 ;
}
intVectorExample1[0] -> 0
intVectorExample1[1] -> 0
intVectorExample1[2] -> 0
intVectorExample1[3] -> 0
intVectorExample1[4] -> 0
If you did not want to initialise a vector with
values at the point of creation, then they can also be
created by providing a default size. This can be an
arbitrary number, as you should recall from earlier that
our vectors can grow in size dynamically. To do this, we
create our vector as normal, but instead of initialising
the vector with a set of curly braces, we append a set
of round brackets at the end of our variable name.
The round brackets will accept two parameters, the
size of our vector and the default value to be
populated. In the example shown on the screen, you can
see that we have created a vector that will store an
integer value. At the end of our variable name in the
set of round brackets, you can see that we declared the
value five and zero. This means that the C++ compiler
will create a vector and reserve five memory blocks and
fill it with a default value of zero. As you can see on
the screen, when it comes to printing each index of our
vector, you can see there are five indices in total,
zero to four, and each index has been given value
zero.
Vectors (5)
Accessing a
Vectors Element i
The items in a vector can be accessed by referring
to its index number inside a set of square brackets
([]
)
remember that the index of a vector begins
at 0
in C++
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
for ( int i = 0 ; i < charVectorExample1. size(); i++) {
std:: cout << "charVectorExample1[" << i << "] -> " << charVectorExample1[ i] << std:: endl;
}
return 0 ;
}
charVectorExample1[0] -> a
charVectorExample1[1] -> b
charVectorExample1[2] -> c
charVectorExample1[3] -> d
charVectorExample1[4] -> e
Accessing an element of a vector are very similar to
the process of an array. Essentially, we need to call
the name of our variable that holds the vector, and
place a set of square brackets at the end. Inside the
set of square brackets we provide an index number in
order to access that element.
It is important to remember that just like arrays,
vectors also begin at index zero and
not one. On the screen, you will see an
example of an array that holds five characters. In the
blue box, you will also see that I am accessing the
variables that are stored at indices, zero to four. Each
of these indices returns the corresponding character
that is stored at that given index. For example, index
zero returns 'a'
and index three returns
'd'
.
Vectors (6)
Accessing a
Vectors Element ii
Alternatively, elements in a vector can be accessed
by using the at()
function
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
for ( int i = 0 ; i < charVectorExample1. size(); i++) {
std:: cout << "charVectorExample1.at(" << i << ") -> " << charVectorExample1. at( i) << std:: endl;
}
return 0 ;
}
charVectorExample1.at(0) -> a
charVectorExample1.at(1) -> b
charVectorExample1.at(2) -> c
charVectorExample1.at(3) -> d
charVectorExample1.at(4) -> e
The at()
function is preferred
throw an exception if trying to access an
out-of-bounds index
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
try {
std:: cout << "charVectorExample1[5] -> " << charVectorExample1[ 5 ] << std:: endl;
std:: cout << "charVectorExample1.at(5) -> " << charVectorExample1. at( 5 ) << std:: endl;
} catch ( std:: out_of_range & e) {
std:: cout << e. what() << std:: endl;
}
return 0 ;
}
charVectorExample1[5] ->
charVectorExample1.at(5) -> vector::_M_range_check: __n (which is 5) >= this->size() (which is 5)
An alternative method for accessing an element at a
given location is by using the at
function.
Similar to the square bracket notation, the
at
function will accept a single parameter
which is the index number. As you can see from the first
example on the screen, when the at
function
is called, an index number is provided, the
corresponding value is returned to the screen.
This is the preferred method of retrieving an element
from a vector, as it throws an exception if it trys to
access an index that is out-of-bounds. Essentially, this
means that you are trying to access an index that does
not exist. You can see in the second example that I am
attempting to access index five using both the square
brackets notation and the at
function.
You will see from the output that when using the
square brackets notation, that an empty value is
returned. The compiler attempted to access the index,
found it did not exist, and as such, it returned
nothing. However, if I attempted to access the same
index using the at
function, an error would
be raised. However, for the purpose of this example, I
have caught the error using a try...catch
clause. This means that if an error is raised, instead
of forcibly exiting the application, I can handle the
error myself. In this instance, I actually print the
output of the error message to the screen.
We can see that the at
function returns
the following message:
"vector m range check, n which is 5 >= this size which is 5"
.
The message that is returned is pretty self-explanatory,
although it does not look it. All it is telling us is
that the compiler attempted to access index location
five, however, the vector size itself is five and as
such, there is no element to be accessed.
Vectors (7)
Getting the Size
of a Vector
Vectors have an inbuilt function to get the
size
Achieved by calling the function size()
on the vector
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
charVectorExample1.size();
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
std:: cout << "charVectorExample1.size() -> " << charVectorExample1. size() << std:: endl;
return 0 ;
}
charVectorExample1.size() -> 5
Unlike arrays, the size of a vector is relatively
trivial to get. Luckily for us, the vector data type has
an inbuilt function called size
which
returns the length of the vector. On the screen you can
see an example from earlier, whereby a vector has been
created storing the first five letters of the alphabet
as a character. When the size
function is
applied to this variable, you can see that the value
five has been returned.
This in-built method of vectors can make it a lot
easier when it comes to looping through the vectors for
algorithms such as searching or sorting.
Vectors (8)
Inserting
Elements into a Vector
The elements in a vector are
ordered and indexed ,
therefore modifiable
otherwise known as being mutable
Elements can be added to a vector by using the
push_back()
function
this will insert an element at the end of the
vector
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
charVectorExample1.push_back('f');
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
charVectorExample1. push_back( 'f' );
for ( int i = 0 ; i < charVectorExample1. size(); i++) {
std:: cout << "charVectorExample.at(" << i << ") -> " << charVectorExample1. at( i) << std:: endl;
}
return 0 ;
}
charVectorExample.at(0) -> a
charVectorExample.at(1) -> b
charVectorExample.at(2) -> c
charVectorExample.at(3) -> d
charVectorExample.at(4) -> e
charVectorExample.at(5) -> f
The next example we shall be looking at is the
process of inserting an element into a vector. Due to
the properties of vectors in the C++ programming
language, whereby they are ordered and indexed, this
means they can be modified. Items can easily be inserted
into a vector by using a function called
push_back
.
For example, on the screen we have our variable
charVectorExample1
which has been created
to reserve five blocks of memory, and initialised with
'a'
, 'b'
, 'c'
,
'd'
, and 'e'
.
In order to insert a new element into our vector, we
can call the push_back
function which is
appended to the end of our variable name and populated
with a new character we wish to add to the vector. In
this case, I wish to store the value
'f'
.
You will see in the blue box on the screen that when
I access each index of the vector and display it to the
screen, the stored value is returned. You will see that
index five has been created and the value
'f'
has been stored. Initially, when we
created our vector, the size of the vector was five, as
we had values for the first five letters of the alphabet
stored within it. However, when we used the
push_back
function to add our sixth letter,
'f'
, it increased the size of the vector
dynamically to ensure it can be added. This is a major
advantage over arrays in C++, as we do not need to
manually create new arrays and copy the contents
across.
Vectors (9)
Replacing an
Element in a Vector
Elements at a particular index can also be
replaced
Achieve by accessing the index of the element you
wish to replace using the at()
function
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
charVectorExample1.at(2) = 'z';
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
charVectorExample1. at( 2 ) = 'Z' ;
for ( int i = 0 ; i < charVectorExample1. size(); i++) {
std:: cout << "charVectorExample.at(" << i << ") -> " << charVectorExample1. at( i) << std:: endl;
}
return 0 ;
}
charVectorExample.at(0) -> a
charVectorExample.at(1) -> b
charVectorExample.at(2) -> Z
charVectorExample.at(3) -> d
charVectorExample.at(4) -> e
If you wish to replace the element for a given index,
we can use the at
function that was
introduced earlier in order to access the element. Once
the element has been accessed, we can use the assignment
operator, which is the equals character, to assign a new
character.
On the screen, you can see that we have our same
vector example from earlier. In this example, we want to
replace the value that is stored at index two with an
upper-case 'Z'
. As you can see from the
output shown in the blue box, when we access each of the
individual indices using the at
function,
the value at index two has been changed from
'c'
to our new value 'z'
.
This also could have been achieved using the square
brackets notation, but as I explained earlier, using the
at
function raises an error if the index
being accessed is incorrect. Therefore, to ensure
consistency through my lectures, I am using the best
practices that I expect my students to also employ.
Vectors (10)
Removing an
Element from a Vector
Elements can be removed from a vector using the
pop_back()
function
this will remove the last element in the
vector
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
charVectorExample1.pop_back();
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
charVectorExample1. pop_back();
for ( int i = 0 ; i < charVectorExample1. size(); i++) {
std:: cout << "charVectorExample.at(" << i << ") -> " << charVectorExample1. at( i) << std:: endl;
}
return 0 ;
}
charVectorExample.at(0) -> a
charVectorExample.at(1) -> b
charVectorExample.at(2) -> c
charVectorExample.at(3) -> d
charVectorExample1.size();
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
charVectorExample1. pop_back();
std:: cout << "charVectorExample1.size() -> " << charVectorExample1. size() << std:: endl;
return 0 ;
}
charVectorExample1.size() -> 4
Similar to how we can insert an element, when it
comes to removing an element the vector data type
provides us a function to assist us. The name of the
function is pop_back
and it is designed to
remove the last element in the vector.
On the screen we have our example from earlier,
charVectorExample1
, which stores the first
five letters of the alphabet. In this example, we want
to remove the last element of our vector, which in this
case would be letter
e'. To do this, we call the function
pop_back`
on our variable name.
You will see from the outcome that when this line is
executed, the last element of our vector has been
removed. Unlike an array, where the value was merely
shifted to the left, this time the entire index has been
removed from the vector. This can be seen when we call
the size
function on the variable, and it
returns value four.
Vectors (11)
Additional Vector
Functions
These are additional functions that do not need much
explanation…
.clear()
removes all elements
.front()
returns a reference to the
first element
.back()
returns a reference the
last element
.empty()
returns 1
if
the vector is empty
.capacity()
returns the overall
capacity of the vector
The last thing I want to touch upon about vectors,
are some additional functions that I have not got around
to covering in this lecture. There are a few other
functions that are useful and good to know, and in some
cases they might be a little confusing.
You might recall from your first year programming
module that lists can be cleared in their entirety using
a single function. Well, this is also applicable with
the C++ programming language and vectors. We can use the
function clear
to remove all elements in
the vector.
There may be times when you need to refer to the
first and last element of a vector, in this case the
functions front
and back
functions can be used, respectively.
Sometimes, you may need to know if a vector is empty
or not. Therefore, the function empty
can
be used to determine whether it is or not. The function
will return one if the vector is empty, which is
true
in boolean form. It would also return
the inverse if the vector was not empty, in
this case 0
, which is the integer value for
false
.
Finally, the last function I wish to discuss is the
capacity
function, which can be confused
with the size
function. The purpose of this
function is to return the overall
capacity of a vector, that is the number of
elements it can actually hold, and not the number of
elements it is currently holding. This may be
easier to explain when looking back at our slide when we
removed an element.
Vectors (12)
Capacity of a Vector
std::vector<char> charVectorExample1 {'a', 'b', 'c', 'd', 'e'};
charVectorExample1.pop_back();
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
charVectorExample1. pop_back();
for ( int i = 0 ; i < charVectorExample1. size(); i++) {
std:: cout << "charVectorExample.at(" << i << ") -> " << charVectorExample1. at( i) << std:: endl;
}
return 0 ;
}
charVectorExample.at(0) -> a
charVectorExample.at(1) -> b
charVectorExample.at(2) -> c
charVectorExample.at(3) -> d
charVectorExample1.size();
charVectorExample1.capacity();
#include <iostream>
#include <vector>
std:: vector< char > charVectorExample1 { 'a' , 'b' , 'c' , 'd' , 'e' };
int main() {
charVectorExample1. pop_back();
std:: cout << "charVectorExample1.size() -> " << charVectorExample1. size() << std:: endl;
std:: cout << "charVectorExample1.capacity() -> " << charVectorExample1. capacity() << std:: endl;
return 0 ;
}
charVectorExample1.size() -> 4
charVectorExample1.capacity() -> 5
Let’s revisit our example from earlier, where we
removed an element from our vector. You will see on the
screen that we have our variable called
charVectorExample1
, which stores the first
five letters of the alphabet as a character.
We shall use the pop_back
function to
remove the last element of our vector. Once this has
been done, we can check the size of vector by using the
size
function. You will see from the output
on the screen that the size returned is four. So let’s
see how this compares to our capacity
function. You will also see on the screen that when we
call this function it returns value five. But why is
this?
Well contrary to what I said earlier, when I removed
the element using the pop_back
function,
whilst it did remove the element and reduce the overall
size of our vector; there was still some residual memory
reserving going on in the background. This is why the
capacity of our vector is still five.
The memory block for our fifth element was never really
removed and still reserved.
Maps (1)
Maps are used to store multiple items into a single
variable
they are stored as a key:value
pair
A map in C++ Can be compared to a
dictionary in Python
They are considered to be:
ordered : the items have a defined
order, and this order will not change when new items are
added to the map
changeable : the items of a map are
mutable (can be changed), added or removed
no duplicates allowed : maps are
unable to have the same key twice
The map
library needs to be imported in
order to use them
#include <map>
You might be noticing a bit of pattern with these
slides, and that they are mimicking alternatives to some
advanced data types that you would have used in the
Python programming language. So far, I have covered
arrays and vectors, with both of these being an
alternative to lists in Python. Now we shall be moving
on and looking at an alternative to the dictionary data
type. Handily for us, the C++ programming language has
an equivalent, and it is known as a
map
.
You should remember from your first year programming
module, that a dictionary stores elements as a
key:value
pair, and this is also applied to
maps in C++. Maps also have the ability to store
multiple items of the same data type
for the value in a key:value
pair; this
could be either an integer, boolean or a double.
Maps, just like arrays and vectors, are considered to
be ordered, changeable and allowable of duplicates. When
we say that a map is ordered, it is meant that the items
have a defined order, and this order will not change.
For example, when a map is initially constructed, a
value would have been placed at a particular position
(or key). Over the course of developing your script or
application, you may want to add another item to the
map. When adding another item, the order in which the
items have been stored does not change. As such, any map
in C++ is considered to be ordered .
Maps are also considered to be mutable, which, in
essence, means that we change them by adding or removing
values.
Finally, maps cannot have duplicated values, in the
sense of the key that will be used to access the
information. However, this does not mean that the value
stored in the key can be duplicated. For example,
keyA
and keyB
could both store
the value 5062CEM
and there would be no
issue.
Maps (2)
Creating a Map
Maps are created by calling the map
data type, followed by a set of angled brackets
(<>
)
Inside the angle brackets are the data types for the
key and value
std::map<key_dataType, value_dataType> mapName;
The items inside the map can only be of the data
type that was assigned to the key and value
std::map<int, std::string> mapExample1; // Stores the key as a integer, and values as a string
std::map<std::string, std::string> mapExample2; // Stores the key as a string, and values as astring
std::map<std::string, int> mapExample3; // Stores the key as a string, and values as integer
When it comes to creating a map in C++, this can be
achieved by calling the map
data type,
followed by a set of angled-brackets. Inside the angled
brackets will be the data type of the key that will be
used to access a value, and a second data type is
provided which would be the type of data that will be
stored as the value. The items that are stored inside
the map will then be only of that type, similar to how
an array or vector can only hold values of a single data
type.
On the screen, you will see three examples of
declaring a map, with each of them using a different
data type for either the key or value. Let’s have a look
at this in some more depth, and look at the first
example, mapExample1
.
In our first example, we are creating a map data type
that will use integers as a key, and then store a
corresponding value as a string. In order to do this, we
call the map data type, and in a set of angled brackets,
we pass through two arguments. The first argument is the
int
data type, which would declare that our
key is going to be an integer number. The second
parameter we pass through is the string
data type. This will tell the C++ compiler that our
value for a given integer key will be of the type
string
. That’s it; we have created our
first map in C++, which would use a number as a key, and
then only store values of a string data type.
However, you may recall that in Python, we do not
explicitly use integers as our key, and we use a string
instead. This can be replicated in C++, as can be seen
in our second example, mapExample2
. We can
also do the inverse of our first example, and have our
key be a string and the values stored as an integer, as
shown in mapExample3
.
Maps (3)
Initialising a Map
Map can be populated by using the curly braces
({}
) after the variable name
declaration
// Initialising List
std::map<int, std::string> mapExample1 = \
{{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
std::map<std::string, std::string> mapExample2 = \
{{"Lecturer 1", "Ian Cornelius"}, {"Lecturer 2", "Terry Richards"}, {"Lecturer 3", "Daniel Goldsmith"}};
// Uniform Initialising
std::map<int, std::string> mapExample1 \
{{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
std::map<std::string, std::string> mapExample2 \
{{"Lecturer 1", "Ian Cornelius"}, {"Lecturer 2", "Terry Richards"}, {"Lecturer 3", "Daniel Goldsmith"}};
On the previous slide, I discussed the process in
which you would follow to create a map.
However, just like arrays and vectors, maps can also be
initialised upon creation.
Similar to the process of creating a map, however,
after we have provided the data types of our map in the
angled-brackets, we can use the assignment operator (the
equals character) to assign some values to the map. You
will notice on the screen two of the three maps from the
previous slide. However, this time I am assigning some
values upon the map creation. This is achieved using a
set of curly braces after the assignment character. It
is important to note in this example, that we have a
backwards-slash after the equals character, this allows
me to split the assignment values onto a new line for
clarification. This can also be applied in your C++
code, and it will compile as normal.
Inside the curly braces, we can then provide some
values (of the corresponding data type for our map) that
we wish to store. In the mapExample1
variable, we can see that we initially created the map
to store the key as an integer and the value as a
string. Therefore, in order to achieve this, we need to
create our key:value
pair. This is done by
using another set of curly braces, and passing through
two arguments. THe first argument would be our integer
number, which would act as our key. In the case of this
example, I am using 0
, and the second
argument would be the value that we want to assign to
this key. Again, in this example, I am storing the
string "Ian Cornelius"
into the map, and it
will be assigned to our key zero.
For each new key:value
pair we want to
provide, it must be provided as a set using the curly
braces notation. This is similar to the methodology you
were taught when updating dictionaries in the Python
programming language.
Just like vectors, maps can also be initialised in an
alternative method, and this is known as uniform
initialisation . The only difference with this
form is that the assignment operator, the equals
character, has been dropped. This means that after our
variable name has been provided, a set of curly braces
are followed, with the corresponding values that we want
to store placed within them.
Maps (4)
Accessing a Maps
Elements i
The items in a map can be accessed by referring to
its key inside a set of square brackets
([]
)
std::map<int, std::string> mapExample1 = \
{{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
std::map<std::string, std::string> mapExample2 \
{{"Lecturer 1", "Ian Cornelius"}, {"Lecturer 2", "Terry Richards"}, {"Lecturer 3", "Daniel Goldsmith"}};
#include <iostream>
#include <map>
std:: map< int , std:: string> mapExample1 = \
{{ 0 , "Ian Cornelius" }, { 1 , "Terry Richards" }, { 2 , "Daniel Goldsmith" }};
std:: map< std:: string, std:: string> mapExample2 \
{{ "Lecturer 1" , "Ian Cornelius" }, { "Lecturer 2" , "Terry Richards" }, { "Lecturer 3" , "Daniel Goldsmith" }};
int main() {
std:: cout << "mapExample1[0] -> " << mapExample1[ 0 ] << std:: endl;
std:: cout << "mapExample1[2] -> " << mapExample1[ 2 ] << std:: endl;
std:: cout << "mapExample2[ \" Lecturer 1 \" ] -> " << mapExample2[ "Lecturer 1" ] << std:: endl;
std:: cout << "mapExample2[ \" Lecturer 3 \" ] -> " << mapExample2[ "Lecturer 3" ] << std:: endl;
return 0 ;
}
mapExample1[0] -> Ian Cornelius
mapExample1[2] -> Daniel Goldsmith
mapExample2["Lecturer 1"] -> Ian Cornelius
mapExample2["Lecturer 3"] -> Daniel Goldsmith
Accessing an element of a map are very similar to the
process for arrays and vectors. Essentially, we need to
call the name of our variable that holds the vector, and
place a set of square brackets at the end. Inside the
set of square brackets, we then provide the associated
key in order to access the element.
On the screen, you will see an example of two maps
that contain three of the lecturers on your course. Each
map has been constructed in a different manner, with the
first example using integers as a key and the second
example using strings as a key. Accessing the element of
a map is relatively straight forward and uses the square
brackets’ notation.
Let’s have a look at each of the examples on the
screen and explore how we can access the values stored
in the map. In the first example,
mapExample1
we can see that our lecturers
can be accessed by a key, which is an integer.
Therefore, we call our variable name,
mapExample1
and we append a set of square
brackets on the end. Inside the set of square brackets,
we then provide our key. In this case, I am providing
the keys zero and two. You will see from the output on
the screen that the values: "Ian Cornelius"
and "Daniel Goldsmith"
have been
extracted.
This is not the most intuitive way of creating our
maps, as they look very similar to how we would extract
information from an array or vector. One of the key
advantages with maps is that they can use a string as
their key to provide a more descriptive access point to
extract information. For example, in our second example,
mapExample2
you can see that I have used
strings as our key data type. This has enabled me to use
a more descriptive name for the values that are being
stored, although you could argue that
Lecturer 1
and Lecturer 2
are
not that descriptive.
You will see in our second example that I have
adjusted the method in which I access the elements of
our map. Instead of calling an integer number, I now use
one of our string keys to access the same elements. In
this case, zero has been replaced by
"Lecturer 1"
and two has been replaced by
"Lecturer 3"
. You can see from the output
on the screen that the same values have been
returned.
Maps (5)
Accessing a Maps
Elements ii
Alternatively, elements in a map can be accessed by
using the at()
function
std::map<int, std::string> mapExample1 = \
{{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
#include <iostream>
#include <map>
std:: map< int , std:: string> mapExample1 = \
{{ 0 , "Ian Cornelius" }, { 1 , "Terry Richards" }, { 2 , "Daniel Goldsmith" }};
int main() {
for ( int i = 0 ; i < mapExample1. size(); i++) {
std:: cout << "mapExample1.at(" << i << ") -> " << mapExample1. at( i) << std:: endl;
}
return 0 ;
}
mapExample1.at(0) -> Ian Cornelius
mapExample1.at(1) -> Terry Richards
mapExample1.at(2) -> Daniel Goldsmith
The at()
function is preferred
throw an exception if trying to access an
out-of-bounds index
std::map<int, std::string> mapExample1 = \
{{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
#include <iostream>
#include <map>
std:: map< int , std:: string> mapExample1 = \
{{ 0 , "Ian Cornelius" }, { 1 , "Terry Richards" }, { 2 , "Daniel Goldsmith" }};
int main() {
try {
std:: cout << "mapExample1[5] -> " << mapExample1[ 5 ] << std:: endl;
std:: cout << "mapExample1.at(5) -> " << mapExample1. at( 5 ) << std:: endl;
} catch ( std:: out_of_range & e1) {
std:: cout << e1. what() << std:: endl;
}
return 0 ;
}
mapExample1[5] ->
mapExample1.at(5) ->
An alternative method for accessing an element at a
given location is by using the at
function.
Similar to the square bracket notation, the
at
function will accept a single parameter
which is the key. As you can see from the first example
on the screen, when the at
function is
called, the key is provided and the corresponding value
is returned to the screen.
This is the preferred method of retrieving an element
from a map, as it throws an exception if it trys to
access a key that is out-of-bounds. Essentially, this
means that you are trying to access a key that does not
exist in the map. You can see in the second example that
I am attempting to access a key using
Lecturer 5
, using both the square brackets
notation and the at
function.
You will see from the output that when using the
square brackets notation, that an empty value is
returned. The compiler attempted to access the key,
found it did not exist, and as such, it returned
nothing. However, if I attempted to access the same key
using the at
function, an error would be
raised. However, for the purpose of this example, I have
caught the error using a try...catch
clause. This means that if an error is raised, instead
of forcibly exiting the application, I can handle the
error myself. In this instance, I actually print the
output of the error message to the screen.
We can see that the at
function returns
the following message:
"map m range check, n which is 5 >= this size which is 5"
.
The message that is returned is pretty self-explanatory,
although it does not look it. All it is telling us is
that the compiler attempted to access the key…
Maps (6)
Getting the Size of a
Map
Maps have an inbuilt function to get the size
Achieved by calling the function size()
on the vector
std::map<int, std::string> mapExample1 = \
{{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
mapExample1.size();
#include <iostream>
#include <map>
std:: map< int , std:: string> mapExample1 = \
{{ 0 , "Ian Cornelius" }, { 1 , "Terry Richards" }, { 2 , "Daniel Goldsmith" }};
int main() {
std:: cout << "mapExample1.size() -> " << mapExample1. size() << std:: endl;
return 0 ;
}
Similar to vectors, the size of a map is relatively
trivial to get. Luckily for us, the map data type has an
inbuilt function called size
which returns
the length of the map. On the screen you can see an
example from earlier, whereby a map has been created
storing three lecturers on the course you are studying.
When the size
function is applied to this
variable, you can see that value three has been
returned.
Maps (7)
Inserting
Elements into a Map i
The elements in a map are ordered
and indexed , therefore modifiable
otherwise known as being mutable
Elements can be added to a vector by using the
insert()
function
used in conjunction with the
make_pair()
function
std::map<int, std::string> mapExample1 = \
{{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
mapExample1.insert(std::make_pair(3, "Kabiru Mohammed")); // Alternative to mapExample1.insert({3, "Kabiru Mohammed"});
#include <iostream>
#include <map>
std:: map< int , std:: string> mapExample1 = \
{{ 0 , "Ian Cornelius" }, { 1 , "Terry Richards" }, { 2 , "Daniel Goldsmith" }};
int main() {
mapExample1. insert( std:: make_pair( 3 , "Kabiru Mohammed" ));
for ( int i = 0 ; i < mapExample1. size(); i++) {
std:: cout << "mapExample1.at(" << i << ") -> " << mapExample1. at( i) << std:: endl;
}
return 0 ;
}
mapExample1.at(0) -> Ian Cornelius
mapExample1.at(1) -> Terry Richards
mapExample1.at(2) -> Daniel Goldsmith
mapExample1.at(3) -> Kabiru Mohammed
The next example we shall be looking at is the
process of inserting an element into a map. Due to the
properties of maps in the C++ programming language,
whereby they are ordered and indexed, this means they
can be modified. Items can easily be inserted into a map
by using a function called insert
. It is
used in conjunction with the make_pair
function.
For example, on the screen we have our variable
mapExample1
which already contains three
lecturers, Ian Cornelius
,
Terry Richards
, and
Daniel Goldsmith
. However, we wish to add
one further lecturer to our map,
Kabiru Mohammed
.
In order to insert a new element into our map, we can
call the insert
function which is appended
to the end of our variable name. Inside this function,
we pass through an argument which makes uses of the
make_pair
function. This is an alternative
method to use the curly braces to create our
key:value
pair. Both methods are
acceptable, with the latter saving some time with fewer
characters to type.
Inside the make_pair
function, I provide
the values I wish to add to our dictionary. In this
case, I am creating a new key, which is the integer
number three, followed by a second argument, which is
the name of the lecturer I want to insert. You will see
in the blue box on the screen that when I access each
key of the map and display it to the screen, the stored
value is returned. You will see that the key has been
created and the value Kabiru Mohammed
has
been stored.
Maps (8)
Inserting
Elements in a Map ii
Alternatively, elements can be added to a vector by
using the square brackets ([]
) notation
a new key is provided inside the square
brackets
std::map<int, std::string> mapExample1 = \
{{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
std::map<std::string, std::string> mapExample2 \
{{"Lecturer 1", "Ian Cornelius"}, {"Lecturer 2", "Terry Richards"}, {"Lecturer 3", "Daniel Goldsmith"}};
mapExample1[3] = "Kabiru Mohammed";
mapExample2["Lecturer 4"] = "Kabiru Mohammed";
#include <iostream>
#include <map>
std:: map< int , std:: string> mapExample1 = \
{{ 0 , "Ian Cornelius" }, { 1 , "Terry Richards" }, { 2 , "Daniel Goldsmith" }};
std:: map< std:: string, std:: string> mapExample2 \
{{ "Lecturer 1" , "Ian Cornelius" }, { "Lecturer 2" , "Terry Richards" }, { "Lecturer 3" , "Daniel Goldsmith" }};
int main() {
mapExample1[ 3 ] = "Kabiru Mohammed" ;
mapExample2[ "Lecturer 4" ] = "Kabiru Mohammed" ;
for ( int i = 0 ; i < mapExample1. size(); i++) {
std:: cout << "mapExample1.at(" << i << ") -> " << mapExample1. at( i) << std:: endl;
std:: cout << "mapExample2.at( \" Lecturer " << std:: to_string( i + 1 ) << " \" ) -> " << mapExample2. at( "Lecturer " + std:: to_string( i + 1 )) << std:: endl;
}
return 0 ;
}
mapExample1.at(0) -> Ian Cornelius
mapExample2.at("Lecturer 1") -> Ian Cornelius
mapExample1.at(1) -> Terry Richards
mapExample2.at("Lecturer 2") -> Terry Richards
mapExample1.at(2) -> Daniel Goldsmith
mapExample2.at("Lecturer 3") -> Daniel Goldsmith
mapExample1.at(3) -> Kabiru Mohammed
mapExample2.at("Lecturer 4") -> Kabiru Mohammed
New elements can be inserted into a map by also using
the square bracket notation. This is similar to the
process you would have used for arrays and also in
Python, when adding a new key to a dictionary.
On the screen, you will see our example consisting of
three lecturers. Just like the slide before, I wish to
add Kabiru Mohammed
to my map of lecturers.
To do this, I call the variable name storing my
lecturers, mapExample1
and I append a set
of square brackets at the end. Inside these square
brackets, I provide the new key for which I want to
refer to my value as. In this case, I am going to
provide numeric value three followed by the assignment
operator and the string equivalent of the lecturer I
want to store at this key.
The same process can also be done for keys that are a
string as well. Instead of providing a numeric value as
we did in my first example, this time I am going to be
using a string to insert the new lecturer. As you can
see from the output on the screen, we can iterate
through our map using a for
loop to extract
each element, either by accessing the integer or string
key.
Maps (9)
Replacing an
Element in a Map
Elements at a particular index can also be
replaced
Achieve by accessing the index of the element you
wish to replace using the at()
function
std::map<int, std::string> mapExample1 = {{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
mapExample1.at(2) = "Kabiru Mohammed";
#include <iostream>
#include <map>
std:: map< int , std:: string> mapExample1 = {{ 0 , "Ian Cornelius" }, { 1 , "Terry Richards" }, { 2 , "Daniel Goldsmith" }};
int main() {
mapExample1. at( 2 ) = "Kabiru Mohammed" ;
for ( int i = 0 ; i < mapExample1. size(); i++) {
std:: cout << "mapExample1.at(" << i << ") -> " << mapExample1. at( i) << std:: endl;
}
return 0 ;
}
mapExample1.at(0) -> Ian Cornelius
mapExample1.at(1) -> Terry Richards
mapExample1.at(2) -> Kabiru Mohammed
If you wish to replace the element for a given key,
we can use the at
function that was
introduced earlier in order to access the element. Once
the element has been accessed, we can use the assignment
operator, which is the equals character, to assign a new
character.
On the screen, you can see that we have our same map
example from earlier. In this example, we want to
replace the value that is stored at key two with
Kabiru Mohammed
. As you can see from the
output shown in the blue box, when we access each of the
individual indices using the at
function,
the value at index two has been changed from
Daniel Goldsmith
to our new value
Kabiru Mohammed
.
This also could have been achieved using the square
brackets notation, but as I explained earlier, using the
at
function raises an error if the key
being accessed is incorrect. Therefore, to ensure
consistency through my lectures, I am using the best
practices that I expect my students to also employ.
Maps (10)
Removing an
Element from a Map
Elements can be removed from a map using the
erase()
function
this will remove the element in the map with the
provided key
std::map<int, std::string> mapExample1 = {{0, "Ian Cornelius"}, {1, "Terry Richards"}, {2, "Daniel Goldsmith"}};
mapExmaple1.erase(1);
#include <iostream>
#include <map>
std:: map< int , std:: string> mapExample1 = {{ 0 , "Ian Cornelius" }, { 1 , "Terry Richards" }, { 2 , "Daniel Goldsmith" }};
int main() {
mapExample1. erase( 1 );
for ( auto const & item : mapExample1) {
std:: cout << "mapExample1.at(" << item. first << ") -> " << mapExample1. at( item. first) << std:: endl;
}
return 0 ;
}
mapExample1.at(0) -> Ian Cornelius
mapExample1.at(2) -> Daniel Goldsmith
Similar to how we can insert an element, when it
comes to removing an element from the map data type, it
provides us a function to assist us. The name of the
function is erase
and it is designed to an
element by providing a key as an argument.
On the screen we have our example from earlier,
mapExample1
, which stores our lecturers. In
this example, we want to remove
Terry Richards
from our map. To do this, we
call the function erase
on our variable
name, and provide the key for the relevant lecturer, in
this case it is key one.
You will see from the outcome that when this line is
executed, the element has been removed. However, due to
the nature of how we constructed our keys by using an
integer number, it means we are now missing our key one.
Therefore, if we were iterating through our map to print
the values using a range, an error would arise. In such
cases, we would need to find an alternative method to
iterate through our map, or use a better naming
convention for our keys, possibly by using a string.
Maps (11)
Additional Map
Functions
These are additional functions that do not need much
explanation…
.clear()
removes all elements
.find()
searches the map for a
given key and returns
.empty()
returns 1
if
the map is empty
The last thing I want to touch upon about maps, are
some additional functions that I have not got around to
covering in this lecture. There are a few other
functions that are useful and good to know.
You might recall from your first year programming
module that lists can be cleared in their entirety using
a single function. Well, this is also applicable with
the C++ programming language and maps. We can use the
function clear
to remove all elements in
the map.
There may be cases whereby you need to find a
particular value, especially if you know the key and
want to access the value directly. In this instance, the
find
function is useful. It will search the
map for an element with the provided key, and return an
iterator to it. This then enables you to access the
value for that given key.
Finally, you may need to know if a map is empty or
not. Therefore, the function empty
can be
used to determine whether it is or not. The function
will return one if the map is empty, which is
true
in boolean form. It would also return
the inverse if the map was not empty, in this
case 0
, which is the integer value for
false
.