All C++ Exercises

Remove duplicates from a vector and keep the order

Description: Remove the duplicates from {4, 7, 4, 1, 7, 9, 1} and keep the order of the first appearance.

Hint:

  • Keep an std::unordered_set of the values you have seen.

Solution

#include <iostream>
#include <unordered_set>
#include <vector>

int main() {
    std::vector<int> numbers = {4, 7, 4, 1, 7, 9, 1};
    std::unordered_set<int> seen;
    std::vector<int> unique;
    for (int n : numbers) {
        if (seen.insert(n).second) {          // insert returns true when it is new
            unique.push_back(n);
        }
    }
    for (int n : unique) std::cout << n << ' ';
    std::cout << '\n';
}
Output

4 7 1 9

How it works

  • insert returns a pair, and the second part is false when the value was already there.

Read STL Containers.

Filter and sum numbers with algorithms and ranges

Description: From the numbers 1 to 10: keep the even ones, square them, print them and print the sum.

Hint:

  • std::views::filter and std::views::transform, and std::accumulate.

Solution

#include <iostream>
#include <numeric>
#include <ranges>
#include <vector>

int main() {
    auto squares = std::views::iota(1, 11)
                 | std::views::filter([](int n) { return n % 2 == 0; })
                 | std::views::transform([](int n) { return n * n; });

    int sum = 0;
    for (int x : squares) {
        std::cout << x << ' ';
        sum += x;
    }
    std::cout << '\n' << "Sum: " << sum << '\n';
}
Output

4 16 36 64 100
Sum: 220

How it works

  • iota(1, 11) makes the numbers 1 to 10, and the pipeline filters and changes them lazily.

Read Modern C++ Features.

Read a file and count its lines and words

Description: Write poem.txt with three lines, then read it and print the number of lines and words.

Hint:

  • std::getline reads a line, and an istringstream counts the words of the line.

Solution

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::ofstream("poem.txt") << "Roses are red\nViolets are blue\nC++ is fun\n";

    std::ifstream in("poem.txt");
    std::string line;
    int lines = 0, words = 0;
    while (std::getline(in, line)) {
        lines++;
        std::istringstream ls(line);
        std::string w;
        while (ls >> w) words++;
    }
    std::cout << "Lines: " << lines << '\n' << "Words: " << words << '\n';
}
Output

Lines: 3
Words: 9

How it works

  • The first stream is closed at the end of the line (RAII), so the file is complete before we read it.

Read C++ File Handling.

Manage a resource with unique_ptr

Description: Make a class Resource whose constructor and destructor print a message. Create it with std::make_unique, move it into a function which takes ownership, and see when it is destroyed.

Hint:

  • A unique_ptr can not be copied, only moved with std::move.

Solution

#include <iostream>
#include <memory>

struct Resource {
    Resource()  { std::cout << "created\n"; }
    ~Resource() { std::cout << "destroyed\n"; }
};

void consume(std::unique_ptr<Resource> r) {
    std::cout << "consume has the resource\n";
}   // r goes out of scope here: the resource is destroyed

int main() {
    auto r = std::make_unique<Resource>();
    consume(std::move(r));
    std::cout << "after consume, empty: " << (r == nullptr) << '\n';
}
Output

created
consume has the resource
destroyed
after consume, empty: 1

How it works

  • std::move gives the ownership to the function. After that, r in main is empty.
  • The destructor ran at the end of consume, with no delete in our code.

Read Smart Pointers.