Skip to content
Theory · Final Project · lesson 1 of 3

Final project: a catalog and a warehouse

What you'll learn

What you'll learn:

  • combine a container, strings and const methods in one class;
  • write methods that return false and change nothing when they refuse;
  • change the elements of a vector in a range-for loop through a reference;
  • read the output of the checks and start with the first failed one.
A card drawer: a slip lend(2) leads to a card stamped lent and comes back stamped false

Picture a librarian at the desk. In front of them is a drawer of book cards, one card per book. A reader brings a slip with a book's number. The librarian finds its card and checks whether it carries a "lent" stamp. If the stamp is already there, the librarian hands the slip back with a refusal and touches nothing in the drawer.

A class in a real program works the same way: it keeps data in a container, takes a request and checks whether the operation is allowed. The analogy differs from the code in one point: a method does not explain why it refuses; it only returns false. The two exercises of the final project are exactly like that: they introduce no new constructs; you combine familiar ones.

Two exercises

The catalog keeps books—Book structs with a number, a title, an author and a lent-out flag. It finds an author's books, lends a book out by its number and takes it back. The warehouse counts how many units of each item it holds. An item may be a string, a number or a value of another type, so the warehouse is a class template.

ExerciseWhat it needs
Book cataloga class, const methods, std::vector, std::string and std::string_view
Generic warehousea class template, a const method, std::map

An operation can be impossible: lending a book that is already lent out, or taking more than there is. Then the method returns false and changes nothing.

How to proceed

Start with the fields and the add method: without them, the other methods have nothing to work with. Then write one method at a time and run the tests after each.

The tests call the methods in turn, and the result of each call depends on the calls before it. So start with the first failed check: the ones after it often fail because of it.

Reading a check

A check that passes prints nothing. A check that fails prints a line marked ✗. This is how the warehouse stub answers the first check:

TEXT
✗ fruit.count("apple") == 8   got: -1

A ✗ line has three parts:

  • left of ==, the call from the test;
  • right of ==, the expected value;
  • after got:, what your code returned.

Here -1 comes from the stub: the count method is not written yet. Below the line are the test file's name and the line where the check is written.

Besides such lines, you will see three other kinds of messages:

  • a check of a condition, such as ✗ fruit.take("apple", 6), has no got: part: the condition turned out false, so take returned false;
  • the summary "Passed n of m" shows how many checks passed;
  • if the program stops abnormally, the line "During check" names the check where it happened.

Common mistake

A range-for loop is meant to change the elements of a vector, but the loop variable is declared without &:

C++
#include <iostream>
#include <vector>

struct Book {
    int id;
    bool lent = false;
};

int main() {
    std::vector<Book> books{{1}, {2}};
    for (Book book : books) {  // ✗
        book.lent = true;
    }
    std::cout << books[0].lent << ' ' << books[1].lent << '\n';  // 0 0
}

The program builds and prints 0 0: on each iteration, book is a copy of the element, and the copy gets true. In the catalog, the tests reveal this mistake: lending the same book a second time returns true again.

Declare the loop variable as a reference: for (Book& book : books). Then the loop changes the elements themselves, and the program prints 1 1.

Press "Next step" and watch books[0]: in the first loop true goes to the copy book, in the second to the element itself.

LiveA copy and a reference in a loopstep 1 of 11 · frames: 1

A vector of two books, neither lent out

Compare book and books[0] after the line book.lent = true

Key points

  • The classes of the final project are built from familiar constructs: a container, strings and const methods.
  • A method that refuses returns false and changes nothing.
  • For a range-for loop to change the elements, declare the loop variable as a reference: Book& book.
  • Start with the first failed check: the ones after it often fail because of it.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way