All C++ Exercises

Print your name and age with variables

Description: Create a std::string for your name and an int for your age. Print My name is Riya and I am 21 years old. with your own values.

Hint:

  • Join the parts with << on std::cout.

Solution

#include <iostream>
#include <print>
#include <string>

int main() {
    std::string name = "Riya";
    int age = 21;
    std::cout << "My name is " << name << " and I am " << age << " years old.\n";
    std::println("My name is {} and I am {} years old.", name, age);
}
Output

My name is Riya and I am 21 years old.
My name is Riya and I am 21 years old.

How it works

  • << sends each part to the output stream, one after the other.
  • std::println (C++23) uses {} placeholders.

Read C++ Variables.

Swap two numbers using a reference function

Description: Write a function swap_values(int& a, int& b) which swaps two variables. Test it with 10 and 25, and compare it with std::swap.

Hint:

  • A reference parameter works on the original variable.

Solution

#include <iostream>
#include <utility>

void swap_values(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 10, y = 25;
    swap_values(x, y);
    std::cout << x << ' ' << y << '\n';
    std::swap(x, y);
    std::cout << x << ' ' << y << '\n';
}
Output

25 10
10 25

How it works

  • Because the parameters are references, the function changes x and y of main, not copies.

Read C++ References.

Convert Celsius to Fahrenheit

Description: Convert 0, 37 and 100 degrees Celsius to Fahrenheit with F = C * 9 / 5 + 32, and print one digit after the decimal point.

Hint:

  • Use double and 9.0 / 5.

Solution

#include <print>

double to_fahrenheit(double c) {
    return c * 9.0 / 5 + 32;
}

int main() {
    for (double c : {0.0, 37.0, 100.0}) {
        std::println("{:.1f} C = {:.1f} F", c, to_fahrenheit(c));
    }
}
Output

0.0 C = 32.0 F
37.0 C = 98.6 F
100.0 C = 212.0 F

How it works

  • 9.0 / 5 is a decimal division. 9 / 5 would be 1 (integer division).
  • {:.1f} prints one digit after the point.

Read C++ Functions.

Find the largest of three numbers

Description: Write largest(int a, int b, int c). Test with (12, 45, 30) and (7, 7, 3).

Hint:

  • Compare with >= and &&, or call std::max with a list.

Solution

#include <algorithm>
#include <iostream>

int largest(int a, int b, int c) {
    if (a >= b && a >= c) return a;
    if (b >= c) return b;
    return c;
}

int main() {
    std::cout << largest(12, 45, 30) << '\n';
    std::cout << largest(7, 7, 3) << '\n';
    std::cout << std::max({12, 45, 30}) << '\n';      // the library way
}
Output

45
7
45

How it works

  • If a is not the biggest, the answer is b or c, so one more check is enough.

Read C++ if else.

Check if a year is a leap year

Description: Write is_leap(int year). Test 1900, 2000, 2024 and 2026.

Hint:

  • Use % and the three rules.

Solution

#include <iostream>

bool is_leap(int year) {
    return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}

int main() {
    std::cout << std::boolalpha;
    for (int y : {1900, 2000, 2024, 2026}) {
        std::cout << y << " -> " << is_leap(y) << '\n';
    }
}
Output

1900 -> false
2000 -> true
2024 -> true
2026 -> false

How it works

  • 1900 is divisible by 100 but not by 400, so it is not a leap year. 2000 is divisible by 400, so it is.

Read C++ Operators.

FizzBuzz in C++

Description: Print 1 to 15. For multiples of 3 print Fizz, for multiples of 5 Buzz, for both FizzBuzz.

Hint:

  • Check the multiples of 15 first.

Solution

#include <iostream>

int main() {
    for (int i = 1; i <= 15; i++) {
        if (i % 15 == 0)      std::cout << "FizzBuzz\n";
        else if (i % 3 == 0)  std::cout << "Fizz\n";
        else if (i % 5 == 0)  std::cout << "Buzz\n";
        else                  std::cout << i << '\n';
    }
}
Output

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

How it works

  • The most special case (15) must be checked first, or it would print only Fizz.

Read C++ for Loop.

Sum of the digits of a number

Description: Write digit_sum(int n). For 9475 the answer is 25.

Hint:

  • n % 10 is the last digit, n / 10 removes it.

Solution

#include <iostream>

int digit_sum(int n) {
    int sum = 0;
    while (n > 0) {
        sum += n % 10;
        n /= 10;
    }
    return sum;
}

int main() {
    std::cout << digit_sum(9475) << ' ' << digit_sum(100) << ' ' << digit_sum(0) << '\n';
}
Output

25 1 0

How it works

  • The loop adds the last digit and cuts it off, until the number is 0.

Read C++ while Loop.

Print a multiplication table

Description: Print 7 x 3 = 21 for 1 to 10.

Hint:

  • A for loop and a format with a width, like {:2}.

Solution

#include <print>

int main() {
    int n = 7;
    for (int i = 1; i <= 10; i++) {
        std::println("{} x {:2} = {:2}", n, i, n * i);
    }
}
Output

7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70

How it works

  • {:2} uses at least 2 places, so the numbers line up.

Read C++ for Loop.

Check prime numbers and list the primes up to 30

Description: Write is_prime(int n) and print the primes from 1 to 30.

Hint:

  • Test divisors while i * i <= n.

Solution

#include <iostream>

bool is_prime(int n) {
    if (n < 2) return false;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) return false;
    }
    return true;
}

int main() {
    for (int n = 1; n <= 30; n++) {
        if (is_prime(n)) std::cout << n << ' ';
    }
    std::cout << '\n';
}
Output

2 3 5 7 11 13 17 19 23 29

How it works

  • If n has a divisor bigger than its square root, it also has a smaller one, so we can stop early.

Read C++ Functions.

Reverse a string

Description: Reverse "C++ Rocks".

Hint:

  • std::reverse is in <algorithm>. A string can also be built from rbegin() and rend().

Solution

#include <algorithm>
#include <iostream>
#include <string>

int main() {
    std::string s = "C++ Rocks";

    std::string a;
    for (int i = static_cast<int>(s.size()) - 1; i >= 0; i--) a += s[i];

    std::string b = s;
    std::reverse(b.begin(), b.end());

    std::string c(s.rbegin(), s.rend());
    std::cout << a << '\n' << b << '\n' << c << '\n';
}
Output

skcoR ++C
skcoR ++C
skcoR ++C

How it works

  • The three ways give the same result. The library way is the shortest and the clearest.

Read C++ Strings.

Check if a string is a palindrome

Description: Write is_palindrome(std::string). Ignore the case and the spaces. Test “Madam”, “Nurses run” and “C++”.

Hint:

  • Clean the text, then compare it with its reverse.

Solution

#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>

bool is_palindrome(std::string s) {
    std::erase_if(s, [](unsigned char c) { return !std::isalnum(c); });
    std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
    return std::equal(s.begin(), s.begin() + s.size() / 2, s.rbegin());
}

int main() {
    std::cout << std::boolalpha;
    for (std::string t : {"Madam", "Nurses run", "C++"}) {
        std::cout << t << " -> " << is_palindrome(t) << '\n';
    }
}
Output

Madam -> true
Nurses run -> true
C++ -> true

How it works

  • We remove everything which is not a letter or digit, and make the rest lower case.
  • std::equal compares the first half with the reversed second half.

Read C++ Strings.

Count the vowels in a string

Description: Count the vowels and the consonants in "Learn C++ Programming".

Hint:

  • Use std::isalpha and look for the letter in "aeiou".

Solution

#include <cctype>
#include <iostream>
#include <string>

int main() {
    std::string text = "Learn C++ Programming";
    int vowels = 0, consonants = 0;
    for (unsigned char c : text) {
        if (!std::isalpha(c)) continue;
        if (std::string("aeiou").find(static_cast<char>(std::tolower(c))) != std::string::npos) vowels++;
        else consonants++;
    }
    std::cout << "Vowels: " << vowels << ", consonants: " << consonants << '\n';
}
Output

Vowels: 5, consonants: 12

How it works

  • Spaces, + signs and other characters are skipped with continue.

Read C++ Strings.

Find the second largest number in a vector

Description: Find the second largest number in {12, 35, 1, 10, 34, 1} without sorting.

Hint:

  • Keep largest and second, and update both in one loop.

Solution

#include <climits>
#include <iostream>
#include <vector>

int second_largest(const std::vector<int>& v) {
    int largest = INT_MIN, second = INT_MIN;
    for (int n : v) {
        if (n > largest) {
            second = largest;
            largest = n;
        } else if (n > second && n != largest) {
            second = n;
        }
    }
    return second;
}

int main() {
    std::cout << second_largest({12, 35, 1, 10, 34, 1}) << '\n';
    std::cout << second_largest({5, 5, 5, 2}) << '\n';
}
Output

34
2

How it works

  • When a bigger value comes, the old biggest becomes the second one.

Read C++ Vectors.

Sort a vector with bubble sort

Description: Sort {64, 34, 25, 12, 22, 11, 90} without std::sort, then check the result with std::sort.

Hint:

  • Swap neighbours which are in the wrong order. Repeat.

Solution

#include <algorithm>
#include <iostream>
#include <vector>

void bubble_sort(std::vector<int>& a) {
    for (std::size_t i = 0; i + 1 < a.size(); i++) {
        bool swapped = false;
        for (std::size_t j = 0; j + 1 < a.size() - i; j++) {
            if (a[j] > a[j + 1]) {
                std::swap(a[j], a[j + 1]);
                swapped = true;
            }
        }
        if (!swapped) break;
    }
}

int main() {
    std::vector<int> data = {64, 34, 25, 12, 22, 11, 90};
    auto check = data;
    bubble_sort(data);
    std::sort(check.begin(), check.end());
    for (int x : data) std::cout << x << ' ';
    std::cout << '\n' << (data == check) << '\n';
}
Output

11 12 22 25 34 64 90
1

How it works

  • After every round of the outer loop, the biggest remaining item is in its place.
  • It is slow (O(n squared)). Real code uses std::sort.

Read C++ Vectors.

Transpose a matrix

Description: Transpose {{1,2,3},{4,5,6}} to {{1,4},{2,5},{3,6}}.

Hint:

  • The new matrix has cols rows and rows columns: t[j][i] = m[i][j].

Solution

#include <iostream>
#include <vector>

using Matrix = std::vector<std::vector<int>>;

Matrix transpose(const Matrix& m) {
    std::size_t rows = m.size(), cols = m[0].size();
    Matrix t(cols, std::vector<int>(rows));
    for (std::size_t i = 0; i < rows; i++)
        for (std::size_t j = 0; j < cols; j++)
            t[j][i] = m[i][j];
    return t;
}

int main() {
    for (const auto& row : transpose({{1, 2, 3}, {4, 5, 6}})) {
        for (int v : row) std::cout << v << ' ';
        std::cout << '\n';
    }
}
Output

1 4
2 5
3 6

How it works

  • A 2 x 3 matrix gives a 3 x 2 matrix, so the new vector has the sizes swapped.

Read C++ Vectors.

Build a BankAccount class

Description: Make a class BankAccount with a private balance. Add deposit and withdraw. Throw an exception for a negative deposit and for a withdraw bigger than the balance.

Hint:

  • Use std::invalid_argument and std::runtime_error.

Solution

#include <iostream>
#include <stdexcept>

class BankAccount {
public:
    void deposit(double amount) {
        if (amount <= 0) throw std::invalid_argument("Deposit must be positive");
        balance += amount;
    }
    void withdraw(double amount) {
        if (amount > balance) throw std::runtime_error("Not enough balance");
        balance -= amount;
    }
    double get_balance() const { return balance; }
private:
    double balance = 0;
};

int main() {
    BankAccount acc;
    acc.deposit(1000);
    acc.withdraw(250);
    std::cout << acc.get_balance() << '\n';
    try {
        acc.withdraw(5000);
    } catch (const std::exception& e) {
        std::cout << "Error: " << e.what() << '\n';
    }
    try {
        acc.deposit(-5);
    } catch (const std::exception& e) {
        std::cout << "Error: " << e.what() << '\n';
    }
}
Output

750
Error: Not enough balance
Error: Deposit must be positive

How it works

  • The balance is private, so only the two methods can change it, and both check the value.

Read Encapsulation.

Calculate areas with polymorphism

Description: Make an abstract class Shape with a pure virtual function area(). Write Circle (radius 2) and Rectangle (3 x 4). Put them in one container and print the total area.

Hint:

  • Use std::vector<std::unique_ptr<Shape>> and a virtual destructor.

Solution

#include <iomanip>
#include <iostream>
#include <memory>
#include <numbers>
#include <vector>

class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;
};

class Circle : public Shape {
public:
    explicit Circle(double r) : r(r) {}
    double area() const override { return std::numbers::pi * r * r; }
private:
    double r;
};

class Rectangle : public Shape {
public:
    Rectangle(double w, double h) : w(w), h(h) {}
    double area() const override { return w * h; }
private:
    double w, h;
};

int main() {
    std::vector<std::unique_ptr<Shape>> shapes;
    shapes.push_back(std::make_unique<Circle>(2));
    shapes.push_back(std::make_unique<Rectangle>(3, 4));

    double total = 0;
    for (const auto& s : shapes) total += s->area();
    std::cout << std::fixed << std::setprecision(2) << "Total area: " << total << '\n';
}
Output

Total area: 24.57

How it works

  • The loop uses the base type. C++ calls the area() of the real object (virtual function).
  • The virtual destructor makes sure that the right destructor runs when the smart pointers delete the objects.

Read Polymorphism and Abstract Classes.

Overload operators for a Money class

Description: Write a class Money which keeps rupees and paise. Overload +, == and <<. Add Rs. 10.75 and Rs. 5.50, and print Rs. 16.25.

Hint:

  • Keep the value in paise (a whole number) to avoid decimal errors.

Solution

#include <iostream>

class Money {
public:
    explicit Money(long long paise) : paise(paise) {}
    Money operator+(const Money& o) const { return Money(paise + o.paise); }
    bool operator==(const Money&) const = default;
    friend std::ostream& operator<<(std::ostream& os, const Money& m) {
        return os << "Rs. " << m.paise / 100 << '.' << (m.paise % 100 < 10 ? "0" : "") << m.paise % 100;
    }
private:
    long long paise;
};

int main() {
    Money a(1075), b(550);
    std::cout << a + b << '\n';
    std::cout << std::boolalpha << (a + b == Money(1625)) << '\n';
}
Output

Rs. 16.25
true

How it works

  • Money is kept as a whole number of paise, so there is no decimal rounding problem.
  • operator<< is a friend function, because the stream is on the left side.

Read Operator Overloading.

Write a generic maximum template

Description: Write a function template max_of which returns the bigger of two values. Use it with int, double and std::string. Then limit it to types which can be compared with a concept.

Hint:

  • std::totally_ordered is a ready concept for comparable types.

Solution

#include <concepts>
#include <iostream>
#include <string>

template <std::totally_ordered T>
T max_of(T a, T b) {
    return a > b ? a : b;
}

int main() {
    std::cout << max_of(3, 9) << '\n';
    std::cout << max_of(2.5, 1.5) << '\n';
    std::cout << max_of(std::string("pear"), std::string("apple")) << '\n';
}
Output

9
2.5
pear

How it works

  • The compiler makes one version of the function for each type you use.
  • The concept gives a clear error when the type can not be compared.

Read C++ Templates.

Count the frequency of words with a map

Description: Count the words of "the cat and the dog and the bird", and print them in alphabetical order.

Hint:

  • std::istringstream reads word by word. std::map keeps sorted keys.

Solution

#include <iostream>
#include <map>
#include <sstream>
#include <string>

int main() {
    std::istringstream in("the cat and the dog and the bird");
    std::map<std::string, int> count;
    std::string word;
    while (in >> word) {
        count[word]++;
    }
    for (const auto& [w, n] : count) {
        std::cout << w << " = " << n << '\n';
    }
}
Output

and = 2
bird = 1
cat = 1
dog = 1
the = 3

How it works

  • count[word]++ creates the key with 0 when it is new, and then adds 1.

Read STL Containers.