On this page

Vectors

A variable holds one value. A program that works with thirty temperatures, or with every number somebody types, would need thirty variables, or a number of variables nobody knows in advance.

A vector holds many values of one type under one name. Module 8 treated a string as a row of characters with numbered positions. A vector is the same idea for any type of value.

Many values under one name

This program keeps five days of rainfall, in millimetres, in one vector.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> rainfall = {12, 0, 7, 31, 4};
    std::cout << "Days measured: " << rainfall.size() << "\n";
}
Days measured: 5

The declaration has four parts.

Part What it is
std::vector the kind of variable: a row of values
<int> the element type: the type of every value in the row
rainfall the name of the whole row
= {12, 0, 7, 31, 4} the starting values, in order, between braces

Each value in a vector is an element. rainfall has five elements. They keep the order in which they were written: 12 is the first and 4 is the last.

rainfall.size() is the number of elements, as s.size() is the number of characters of a string. It counts the elements. It does not add them up.

std::vector comes from the header <vector>, so the program names that header in an #include line.

The element type is part of the vector's type, and every element has it. A std::vector<int> holds ints and nothing else. This program does not compile, because "seven" is text.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> rainfall = {12, 0, "seven"};
    std::cout << rainfall.size() << "\n";
}

Any type you know can stand between the angle brackets. std::vector<double> is a row of numbers with a fraction, and std::vector<std::string> is a row of strings. Most of this lesson uses std::vector<int>; a later section looks at a vector of strings.

Three ways to start a vector

A list in braces is one way to give a vector its first elements. There are two more.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> listed = {3, 5};
    std::vector<int> repeated(3, 5);
    std::vector<int> zeros(4);
    std::vector<int> nothing_yet;

    std::cout << listed.size() << "\n";
    std::cout << repeated.size() << "\n";
    std::cout << zeros.size() << "\n";
    std::cout << nothing_yet.size() << "\n";
}
2
3
4
0
Declaration Elements What the declaration says
std::vector<int> listed = {3, 5}; 3, 5 braces: these are the elements
std::vector<int> repeated(3, 5); 5, 5, 5 parentheses: how many, then the value of each
std::vector<int> zeros(4); 0, 0, 0, 0 parentheses with one number: how many, each of them 0
std::vector<int> nothing_yet; none no elements at all

Braces and parentheses mean different things here, and both compile. {3, 5} is a list of two elements. (3, 5) is an instruction: make three elements, each with the value 5. Read the brackets before you read the numbers.

A vector declared with nothing after its name is empty: its size is 0. That is a proper starting value. Module 2 warned that an int given no value holds whatever was in memory. A vector is different: with no value given, it is always an empty vector, never an unknown one.

The element at a position

Each element has a position, counted from 0, exactly like the characters of a string. v[i] is the element at position i.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> heights = {150, 162, 171, 158};

    std::cout << heights[0] << "\n";
    std::cout << heights[heights.size() - 1] << "\n";

    heights[1] = 165;
    heights[2] += 1;

    int n = heights.size();
    for (int i = 0; i < n; ++i) {
        std::cout << i << ": " << heights[i] << "\n";
    }
}
150
158
0: 150
1: 165
2: 172
3: 158

At the start the vector looks like this.

Position 0 1 2 3
Element 150 162 171 158

Three things to notice.

  • The first element is heights[0]. The size is 4, and the last element is at position 3, which is heights.size() - 1. There is no element at position 4.
  • heights[1] is a variable like any other int. It can be printed, assigned to and updated. heights[1] = 165; replaces one element and leaves the others alone.
  • The loop visits every position: i starts at 0 and the loop runs while i < n, so i takes the values 0, 1, 2 and 3.

The loop stores the size in an int first, as every loop over a string did in module 8. size() gives a std::size_t, which is unsigned, and storing it in an int once means that every comparison and subtraction in the loop is between two ints.

The expression between the square brackets can be any int expression: a number, a variable, or a calculation such as n - 1 - i.

A vector that grows

The size of a vector is not fixed. push_back adds one element at the end.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> laps;
    std::cout << laps.empty() << "\n";

    laps.push_back(74);
    laps.push_back(71);
    laps.push_back(69);
    std::cout << laps.size() << " " << laps.back() << "\n";

    laps.pop_back();
    std::cout << laps.size() << " " << laps.back() << "\n";
    std::cout << laps.empty() << "\n";
}
1
3 69
2 71
0
Call What it does
laps.push_back(74); adds 74 as a new last element; the size goes up by one
laps.pop_back(); removes the last element; the size goes down by one
laps.back() the last element, the same as laps[laps.size() - 1]
laps.empty() true when the size is 0, false otherwise

laps starts empty, so laps.empty() is true and prints as 1. After three calls of push_back it holds 74, 71, 69, in that order: each new element goes after the ones already there. pop_back then removes the 69, and 71 is the last element again.

back() and pop_back() need a last element to work on. On an empty vector C++ does not say what they do. When a vector may be empty, test empty() first.

Growing is what makes a vector fit input of unknown length. This program reads temperatures until the input ends, and only then prints them.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> readings;
    int value = 0;
    while (std::cin >> value) {
        readings.push_back(value);
    }

    int n = readings.size();
    for (int i = 0; i < n; ++i) {
        std::cout << "Reading " << i + 1 << " of " << n << ": " << readings[i] << "\n";
    }
}
18 21 19
Reading 1 of 3: 18
Reading 2 of 3: 21
Reading 3 of 3: 19

The first line of output says of 3. The program could not have printed that while it was still reading: it did not yet know how many values there would be. With the values kept in a vector, the program can finish reading first and then go through them as often as it likes.

One past the end

A vector with three elements has the positions 0, 1 and 2. Position 3 is one past the end. It is the position a loop reaches when its test says <= where it should say <.

int n = v.size();
for (int i = 0; i <= n; ++i) {      // wrong: the last turn uses i == n
    std::cout << v[i] << "\n";
}

What does v[3] give in a vector of three? C++ makes no promise. The square brackets do not check the position. The program may print a number left over in memory, it may stop, or it may seem to work today and fail on another computer. There is no error message to rely on. Positions below 0 are outside the vector in the same way.

A string is slightly different here. Module 8 showed that a string keeps the null character at position size(), so reading s[s.size()] gives that character. A vector, unlike a string, has nothing at position size().

This is worse than a program that stops, because a wrong number can travel a long way before anybody notices it. So the rule is strict: a position used with [] must be at least 0 and less than size(). It is the programmer who makes sure of that. No program in this course uses [] outside a vector, not even to show what happens, because nobody can say what would happen.

A vector has a second way to reach an element, which does check. v.at(i) gives the same element as v[i] when position i exists. When it does not, the program stops at that line.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {5, 6, 7};
    std::cout << v.at(2) << "\n";
    std::cout << v.at(3) << "\n";
    std::cout << "not reached\n";
}

This program prints 7, and then stops at the line with v.at(3). The last line never runs. Like a failed assert in module 7, this is a run-time error that points at the place where things went wrong.

Use [] inside a loop whose test you have checked: with i from 0 while i < n, every position is an element. Use at() when a position comes from input or from a calculation you are less sure of, and while you hunt a bug.

Before you run a loop over a vector, check the two ends by hand. What is i on the first turn? What is i on the last turn, and is that position less than the size?

Each element in turn

Many loops over a vector need each element and do not care about its position. C++ has a second form of for for them.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> rainfall = {12, 0, 7, 31, 4};
    int total = 0;
    for (int amount : rainfall) {
        total += amount;
    }
    std::cout << "Total: " << total << "\n";
}
Total: 54

Read for (int amount : rainfall) as "for each int in rainfall, call it amount". The body runs once for each element, from the first to the last. On the first turn amount is 12, on the second 0, and so on. This form is called a range-based for loop.

There is no position, no test and no update to write, so there is nothing to get wrong by one. A loop of this form cannot go past the end.

The variable before the colon is a new variable on every turn, and it holds a copy of the element. Changing it does not change the vector.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> prices = {4, 9, 6};

    for (int p : prices) {
        p = p * 2;
        std::cout << "copy: " << p << "\n";
    }
    for (int p : prices) {
        std::cout << "element: " << p << "\n";
    }

    int n = prices.size();
    for (int i = 0; i < n; ++i) {
        prices[i] = prices[i] * 2;
    }
    std::cout << "first element now: " << prices[0] << "\n";
}
copy: 8
copy: 18
copy: 12
element: 4
element: 9
element: 6
first element now: 8

The first loop doubled three copies and printed them. The second loop shows that the elements are still 4, 9 and 6. The third loop assigns to prices[i], which is the element itself, and that does change the vector.

You need Use
each element, to read it for (int x : v)
the position as well as the element a loop over positions, with v[i]
to change the elements a loop over positions, with v[i] = ...
only some of the positions, or a different order a loop over positions

The elements can go straight into a picture. Each turn of this loop draws one disc with the next radius, and moves right for the one after.

#include "scimigo.h"
#include <vector>
using namespace scimigo;

int main() {
    canvas(600, 200);
    std::vector<int> sizes = {10, 25, 40, 25, 10};
    int x = 80;
    for (int radius : sizes) {
        circle(x, 100, radius, "teal");
        x += 110;
    }
}

Letting the compiler name the type

Every value in a program has a type, and the compiler always knows it. When a variable is declared with a starting value, you may write auto where the type goes, and the compiler writes the type of that value for you.

#include <iostream>
#include <vector>

int main() {
    std::vector<double> lengths = {2.5, 4.0};

    auto count = 3;
    auto half = 7 / 2;
    auto exact = 7 / 2.0;
    auto first = lengths[0];

    std::cout << count << " " << half << " " << exact << " " << first << "\n";

    for (auto length : lengths) {
        std::cout << length * 2 << "\n";
    }
}
3 3 3.5 2.5
5
8
Declaration Value on the right Type the compiler writes
auto count = 3; 3, an int int
auto half = 7 / 2; int / int, which is the int 3 int
auto exact = 7 / 2.0; int / double, which is the double 3.5 double
auto first = lengths[0]; an element of a std::vector<double> double
for (auto length : lengths) each element of lengths double

auto is not a type that can hold anything. The type is fixed at the declaration, from the value on the right, by the rules you already know. half is an int because 7 / 2 is an int division; auto does not rescue the fraction. Afterwards half is an int for good.

Since the type comes from the starting value, there must be one. This does not compile.

#include <iostream>

int main() {
    auto total;
    total = 5;
    std::cout << total << "\n";
}

Two cases need care.

The first is size(). In auto n = v.size(); the compiler writes std::size_t, the unsigned type that size() gives and that module 8 warned about. It has no negative values, so n - 1 is not -1 when n is 0.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> none;
    auto n = none.size();
    int m = none.size();
    std::cout << (n - 1 < 0) << "\n";
    std::cout << (m - 1 < 0) << "\n";
}
0
1

With auto, n - 1 < 0 is false, although the vector is empty. With int, it is true, as expected. For a size you will subtract from or compare with an int, write int.

The second is text in quotes. auto word = "kite"; does not make a std::string. Text written in quotes has an older type of its own, which module 18 explains. When you want a string, write std::string.

Use auto where the type is plain from the same line, as in a range-based for over a vector you can see. Write the type out where reading it helps.

A vector of strings

The elements of a vector can be strings. Everything so far works the same way.

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> tools = {"hammer", "saw", "chisel"};
    tools.push_back("file");

    std::cout << tools.size() << "\n";
    std::cout << tools[1] << "\n";
    std::cout << tools[1].size() << "\n";
    std::cout << tools[2][0] << "\n";

    for (std::string tool : tools) {
        std::cout << tool << " has " << tool.size() << " letters\n";
    }
}
4
saw
3
c
hammer has 6 letters
saw has 3 letters
chisel has 6 letters
file has 4 letters

Two sizes are in play, and they answer different questions.

  • tools.size() is the number of elements in the vector: 4 strings.
  • tools[1].size() is the number of characters in one element: "saw" has 3.

tools[1] is a std::string, so anything a string can do, it can do: .size(), +, ==, and a second pair of square brackets. tools[2][0] is read from the left: tools[2] is the string "chisel", and [0] is its first character, the char 'c'.

A vector of strings is the natural place for words or lines that are read from input. For words, std::cin >> word in the test of a while loop works as it did for numbers in module 5. For whole lines, std::getline can stand in the test in the same way: while (std::getline(std::cin, line)) is true each time a line was read, and false when the input has run out.

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> items;
    std::string line;
    while (std::getline(std::cin, line)) {
        items.push_back(line);
    }

    std::cout << items.size() << " things to buy\n";
    for (std::string item : items) {
        std::cout << "- " << item << "\n";
    }
}
brown rice
two lemons
tea
3 things to buy
- brown rice
- two lemons
- tea

Each element is one whole line, spaces included.

A function that returns a vector

A vector is a value, so a function can build one and give it back. The return type is the vector's type.

#include <iostream>
#include <vector>

std::vector<int> countdown(int from) {
    std::vector<int> result;
    for (int i = from; i >= 1; --i) {
        result.push_back(i);
    }
    return result;
}

int main() {
    std::vector<int> steps = countdown(4);
    std::cout << steps.size() << " steps\n";
    for (int step : steps) {
        std::cout << step << "\n";
    }
    std::cout << countdown(0).size() << "\n";
}
4 steps
4
3
2
1
0

The pattern has three parts: declare an empty vector, add to it, return it. result is a local variable of countdown and is gone when the call ends, but its value has been handed to the caller, exactly as with an int. main stores it in steps.

For countdown(0) the loop does not run at all, and the function returns an empty vector. An empty vector is a perfectly good answer.

The function builds the vector and main prints it. As in module 6, a function that is asked to return something should not print it.

A vector can also be a parameter. The rule from module 6 holds without any change: the function gets a copy. All the elements are copied into the parameter when the call starts, and whatever the function does to its copy, the caller's vector stays as it was.

#include <iostream>
#include <vector>

std::vector<int> with_bonus(std::vector<int> marks, int bonus) {
    int n = marks.size();
    for (int i = 0; i < n; ++i) {
        marks[i] += bonus;
    }
    return marks;
}

int main() {
    std::vector<int> marks = {52, 67, 48};
    std::vector<int> raised = with_bonus(marks, 5);

    std::cout << marks[0] << " " << marks[1] << " " << marks[2] << "\n";
    std::cout << raised[0] << " " << raised[1] << " " << raised[2] << "\n";
}
52 67 48
57 72 53

with_bonus changes every element of its parameter marks, and returns it. The marks of main is a different vector, and still holds 52, 67 and 48. The changed elements reach main only through the returned value, which main stores in raised.

Copying a vector copies every element, which takes time when the vector is long. Module 10 shows how a function can work on the caller's vector without a copy.

Your turn

Now try it yourself

Predict what a program will do, run it, and step through it line by line. The checks tell you when your own code works.

Loading the lab…

In this lab

  1. Many values, one name

    This program keeps three test scores in one vector and prints one number. Decide what it prints before you run it.

  2. Three ways to start

    Three vectors are declared in three ways. The first uses parentheses, the second uses braces, the third has nothing after its name. The program prints the size of each.

  3. The element at a position

    A vector of four elements. The program prints two of them, then assigns to one, then prints all four on one line.

  4. A vector that grows

    This program reads whole numbers until the input ends and prints how many there were. It forgets each number as soon as the next one is read.

    Change it so that it keeps the numbers in a std::vector<int>, and after the line with the count prints them in reverse order, the last one read first, each on its own line. For the input 12 7 30 4:

    Numbers: 4
    4
    30
    7
    12
    
    1. Add the header that a vector needs.
    2. Declare an empty vector before the loop, and add each number to its end inside the loop.
    3. Print the count from the vector's size. The variable count is no longer needed.
    4. Print the elements with a loop over the positions that starts at the last position and goes down to 0.

    With no numbers in the input, the program prints Numbers: 0 and nothing else.

  5. One past the end

    This program is correct. It prints every element of a vector of three, with its position.

    A colleague then changes one character: the test i < n becomes i <= n.

    for (int i = 0; i <= n; ++i) {
        std::cout << "position " << i << ": " << v[i] << "\n";
    }
    

    Do not make that change yourself. Run the correct program, and answer the questions about the changed loop from what you know.

  6. Each element in turn

    This program reads whole numbers into a vector and adds them up with a loop over the positions. The loop needs the elements only, never their positions.

    Make two changes.

    1. Rewrite the loop that adds up as a loop of the form for (int x : v). When you have finished, no square brackets are left in the program.
    2. After the total, print the average on a second line. For the input 4 9 2 7:
    Total: 22
    Average: 5.5
    

    The input always has at least one number. The average usually has a fraction: 22 divided by 4 is 5.5, not 5.

  7. What type is it?

    Every variable declared with auto in this program has a type, and the compiler has written it. For each one, decide which type it is. The values that are printed are your evidence.

  8. A list of names

    This program reads lines until the input ends, keeps them in a vector of strings, and prints them.

    Make it also print the longest line, the one with the most characters, on one more line at the end. For the four names in the Input box:

    Mina Okafor
    Jo Li
    Bartholomew Finch
    Sam Reyes
    Longest: Bartholomew Finch
    

    If several lines share the greatest length, print the first of them. The input always has at least one line.

  9. A function that makes a vector

    squares_up_to(n) prints the squares 1, 4, 9 and so on, up to n times n. A function that prints can do nothing else with its numbers: main cannot add them up, count them or draw them.

    Change the function so that it returns the squares in a vector and prints nothing. Then let main do the printing.

    1. Make the first line std::vector<int> squares_up_to(int n).
    2. In the body, declare an empty vector, add each square to it where the function printed before, and return it.
    3. In main, store what the call gives back in a vector, and print each element on its own line.

    The program prints the same five lines as before. squares_up_to(0) returns an empty vector.

  10. A bar chart

    Read whole numbers until the input ends, keep them in a vector, and then draw one bar for each number. The bars stand side by side in the order of the input, and the height of each bar is its number.

    The canvas is 600 wide, and the bars share that width equally. So the program has to know how many numbers there are before it can draw the first bar. That is why the numbers are kept in a vector.

    • Each bar gets a slot of 600 / count pixels, where count is how many numbers were read. The first slot starts at x = 0, the second at x = slot, the third at 2 times slot, and so on.
    • A bar starts at the left edge of its slot and is slot - 10 wide, which leaves a gap of 10 before the next one.
    • Every bar stands on the line y = 350: its bottom edge is at 350, and it reaches up from there by its number.
    • The colour is "teal".

    For the input 120 60 200 90 there are four bars. A slot is 150, each bar is 140 wide, and the first bar is rectangle(0, 230, 140, 120, "teal").

    The input has at most 12 numbers, each from 1 to 300. With no numbers at all the program draws no bars, and it must not divide by zero.

  11. index_of_largest

    Write a function that says where the largest element of a vector is. main is given; write the function above it.

    First line: int index_of_largest(std::vector<int> v)

    What it returns: the position of the largest element, counted from 0. When the largest value appears more than once, it returns the position of the first of them. For {14, 19, 23, 17, 23, 9} the answer is 2.

    The caller promises that the vector is never empty, so position 0 is always an element. The elements may be negative.

    A vector parameter is written like any other parameter, the type and then a name. The function gets a copy of the caller's vector. It returns its answer and prints nothing.

    The checks call your function with vectors that main never uses.

  12. evens_only

    Write a function that picks the even numbers out of a vector. main is given; write the function above it.

    First line: std::vector<int> evens_only(std::vector<int> v)

    What it returns: a new vector with the even elements of v, in the same order. An element that appears twice in v appears twice in the answer. 0 is even, and so are -2 and -4. When v has no even elements, the answer is an empty vector.

    v is the function's own copy, so nothing the function does can change the caller's vector. The last line that main prints shows this.

    The function returns its answer and prints nothing.

  13. A word inspector

    Read words until the input ends, and keep them in a vector of strings. Then print a table with one row for each word, and two more lines.

    For the input kite umbrella fig lantern:

      0          kite   4
      1      umbrella   8
      2           fig   3
      3       lantern   7
    Shortest: fig
    Longest: umbrella
    
    • A row has three columns: the position of the word in the vector in a column 3 wide, the word in a column 14 wide, and its length in a column 4 wide. Each column is made with std::setw, which puts the value at the right of its column. There is nothing else between the columns.
    • Then Shortest: and the word with the fewest characters, and Longest: and the word with the most. When several words share that length, print the first of them.

    The input has at least one word, and no word is longer than 12 characters. The headers are yours to choose: name every one that the program uses.

  14. How many above average?

    Read whole numbers until the input ends. Print their average with one digit after the point, and then how many of the numbers are above the average.

    For the input 4 9 2 11 the average is 6.5, and two of the numbers, 9 and 11, are above it:

    Average: 6.5
    Above average: 2
    

    A number equal to the average is not above it. The input always has at least one number.

    The program has to go through the numbers twice: once to find the average, and once more to compare each number with it. That is what the vector is for.

  15. reversed

    Write a function that returns the elements of a vector in the opposite order. main is given; write the function above it.

    First line: std::vector<int> reversed(std::vector<int> v)

    What it returns: a vector of the same size as v, with the last element of v first and the first element of v last. reversed({8, 2, 6, 1}) is {1, 6, 2, 8}. The reverse of an empty vector is an empty vector.

    Every position the function uses must be an element. Check the first and the last turn of your loop by hand before you run it.

    The function returns its answer and prints nothing.

  16. contains

    Write a function that says whether a value is one of the elements of a vector. main is given; write the function above it.

    First line: bool contains(std::vector<int> v, int wanted)

    What it returns: true when at least one element of v equals wanted, and false when none does. For an empty vector the answer is false.

    Think about when each answer is known. One equal element is enough to answer true. The answer false is known only after every element has been looked at.

    The function returns its answer and prints nothing.

  17. running_totals

    Write a function that turns a vector of amounts into a vector of totals so far. main is given; write the function above it.

    First line: std::vector<int> running_totals(std::vector<int> v)

    What it returns: a vector of the same size as v. The element at each position is the sum of the elements of v from position 0 up to and including that position.

    running_totals({3, 1, 4}) is {3, 4, 8}: 3, then 3 + 1, then 3 + 1 + 4. For an empty vector the answer is an empty vector.

    The function returns its answer and prints nothing.

  18. split_words

    Write a function that cuts a line into its words. main is given; write the function above it.

    First line: std::vector<std::string> split_words(std::string line)

    What it returns: the words of line, in order, as a vector of strings. A word is a run of characters that are not spaces. Words are separated by one or more spaces, and the line may begin or end with spaces. No element of the answer is empty, and none contains a space.

    split_words(" the red kite flies ") returns the four strings the, red, kite, flies. For an empty line, or a line of spaces only, it returns an empty vector.

    Go through the line one character at a time, as in module 8, and build the current word in a string. Do not read from std::cin inside the function: it works on the string it is given.

    The function returns its answer and prints nothing.

  19. The loop that went too far

    count_rises should return how many elements of a vector are followed by a larger one. In {2, 5, 3, 8, 8, 9} that happens three times: 2 to 5, 3 to 8 and 8 to 9. So the program should print Rises: 3.

    Press Run. The program stops before it prints anything. The function compares each element with the next one, and on its last turn there is no next one.

    The function uses at, which checks every position. That is why the mistake stops the program here, at the line where it happens, and does not quietly produce a wrong number.

    Repair the loop so that every position it uses is an element. Keep both calls of at as they are. The function must also be right for a vector of one element and for an empty vector: neither has any rises.

  20. Letter counts in a vector

    In module 8 you wrote a letter histogram: read a line, and for each letter from a to z that occurs in it, print the letter and a bar of #, one for each time it occurs. Without a vector, that program has to go through the whole line once for every letter of the alphabet.

    Write it again with one std::vector<int> of 26 elements, all of them 0 at the start, and a single pass over the line.

    • The element at position 0 counts the letter a, position 1 counts b, and so on up to position 25 for z.
    • For each character of the line that is a letter, work out its position from the character itself, as module 8 did with c - 'a', and add 1 to that element. Capitals count as their small letters.
    • After the pass, go through the 26 positions and print a row for each count above 0. The letter for position i is the character 'a' + i, stored in a char.

    Nothing checks this one. Keep your module 8 program open beside it, and go through the list below when you have finished.