This section is included to assist the students to perform the activities in the book. It includes detailed steps that are to be performed by the students to achieve the objectives of the activities.
#include <iostream>
unsigned i = 1;
while ( i < 100){ }
if (i%7 == 0) {
std::cout << i << std::endl;
}
i++;
The output of the program is as follows:
7
14
21
28
...
98
#include <iostream>
int main()
{
int foo[3][3];
for (int x= 0; x < 3; x++){
for (int y = 0; y < 3; y++){
}
}
foo[x][y] = x + y;
for (int x = 0; x < 3; x++){
for (int y = 0; y < 3; y++){
std::cout << “foo[“ << x << “][“ << y << “]: “ << foo[x][y] << std::endl;
}
}
The output is as follows:
foo[0][0]: 0
foo[0][1]: 1
foo[0][2]: 2
foo[1][0]: 1
foo[1][1]: 2
foo[1][2]: 3
foo[2][0]: 2
foo[2][1]: 3
foo[2][2]: 4
#include <iostream>
void byreference_age_in_5_years(int& age) {
if (age >= 18) {
std::cout << “Congratulations! You are eligible to vote for your nation.” << std::endl;
return;
} else{
int reqAge = 18;
int yearsToGo = reqAge-age;
std::cout << “No worries, just “<< yearsToGo << “ more years to go.” << std::endl;
}
}
int main() {
int age;
std::cout << “Please enter your age:”;
std::cin >> age;
byreference_age_in_5_years(age);
}
int sum(int a, int b)
{
return a + b
}
Take by value, return by value, since the types are small in memory and there is no reason to use references.
int& getMaxOf(std::array<int, 10>& array1, std::array<int, 10>& array2, int index) {
if (array1[index] >= array2[index]) {
return array1[index];
} else {
return array2[index];
}
}
#include <iostream>
using namespace std;
namespace LamborghiniCar
{
int output(){
std::cout << “Congratulations! You deserve the Lamborghini.” << std::endl;
return NULL;
}
}
namespace PorscheCar
{
int output(){
std::cout << “Congratulations! You deserve the Porsche.” << std::endl;
return NULL;
}
}
In the main function, create a variable named magicNumber of type integer to accept the input from the user:
int main()
{
int magicNumber;
std::cout << “Select a magic number (1 or 2) to win your dream car: “;
std::cin >> magicNumber;
if (magicNumber == 1){
std::cout << LamborghiniCar::output() << std::endl;
} else if(magicNumber == 2){
std::cout << PorscheCar::output() << std::endl;
}else{
std::cout << “Please type the correct magic number.” << std::endl;
}
}
#include <mathlib.h>
#include <array>
#include <iostream>
const float ENEMY_VIEW_RADIUS_METERS = 5;
int main() {
std::array<float, 3> enemy1_location = {2, 2 ,0};
std::array<float, 3> enemy2_location = {2, 4 ,0};
float enemy_distance = johnny::mathlib::distance(enemy1_location, enemy2_location);
float distance_from_center = johnny::mathlib::distance(enemy1_location);
using johnny::mathlib::circumference;
float view_circumference_for_enemy = circumference(ENEMY_VIEW_RADIUS_METERS);
float total_distance = johnny::mathlib::total_walking_distance({
enemy1_location,
{2, 3, 0}, // y += 1
{2, 3, 3}, // z += 3
{5, 3, 3}, // x += 3
{8, 3, 3}, // x += 3
{8, 3, 2}, // z -= 1
{2, 3, 2}, // x -= 6
{2, 3, 1}, // z -= 1
{2, 3, 0}, // z -= 1
enemy2_location
});
std::cout << “The two enemies are “ << enemy_distance << “m apart and can see for a circumference of “
<< view_circumference_for_enemy << “m. To go to from one to the other they need to walk “
<< total_distance << “m.”;
}
class Coordinates {
private:
float latitude;
float longitude;
};
class Coordinates {
private:
float latitude;
float longitude;
public:
void set_latitude(float value){}
void set_longitude(float value){}
float get_latitude(){}
float get_longitude(){}
};
class Coordinates {
private:
float latitude;
float longitude;
public:
void set_latitude(float value){ latitude = value; }
void set_longitude(float value){ longitude = value; }
float get_latitude(){ return latitude; }
float get_longitude(){ return longitude; }
};
An example is as follows:
#include <iostream>
int main() {
Coordinates washington_dc;
std::cout << “Object named washington_dc of type Coordinates created.” << std::endl;
washington_dc.set_latitude(38.8951);
washington_dc.set_longitude(-77.0364);
std::cout << “Object’s latitude and longitude set.” << std::endl;
std::cout << “Washington DC has a latitude of “
<< washington_dc.get_latitude()
<< “ and longitude of “ << washington_dc.get_longitude() << std::endl;
}
class Coordinates {
private:
float _latitude;
float _longitude;
};
class Coordinates {
public:
Coordinates(float latitude, float longitude)
: _latitude(latitude), _longitude(longitude) {}
private:
int _latitude;
int _longitude;
};
#include <iostream>
int main() {
Coordinates washington_dc(38.8951, -77.0364);
std::cout << “Object named washington_dc of type Coordinates created.”
<< std::endl;
std::cout << “Washington DC has a latitude of “
<< washington_dc.get_latitude()
<< “ and longitude of “ << washington_dc.get_longitude()
<< std::endl;
}
The constructor takes the size of the array as a parameter.
The constructor also takes care of allocating memory, which is used to store the coordinates.
public:
explicit managed_array(size_t size) {
array = new int[size];
std::cout << “Array of size “ << size << “ created.” << std::endl;
}
~managed_array() {
delete[] array;
std::cout << “Array deleted.” << std::endl;
}
private:
int *array;
};
int main() {
managed_array m(10);
}
The output will be as follows:
Array of size 10 created.
Array deleted.
class Apple
{
private:
Apple() {}
// do nothing
};
#include <iostream>
class AppleTree
{
public:
Apple createFruit(){
Apple apple;
std::cout << “apple created!” << std::endl;
return apple;
}
};
class Apple
{
friend class AppleTree;
private:
Apple() {}
// do nothing
}
int main() {
AppleTree tree;
Apple apple = tree.createFruit();
}
This prints the following:
apple created!
class Point
{
public:
bool operator< (const Point &other){
return x < other.x || (x == other.x && y < other.y);
}
int x;
int y;
};
#include <iostream>
int main() {
Point p_1, p_2;
p_1.x = 1;
p_1.y = 2;
p_2.x = 2;
p_2.y = 1;
std::cout << std::boolalpha << (p_1 < p_2) << std::endl;
}
class AddX {
public:
AddX(int x) : x(x) {}
private:
int x;
};
class AddX {
public:
AddX(int x) : x(x) {}
int operator() (int y) { return x + y; }
private:
int x;
};
int main() {
AddX add_five(5);
std::cout << add_five(4) << std::endl;
}
The output will be as follows:
9
#include <iostream>
#include <connection.h>
#include <useraccount.h>
template<typename Object, typename Connection>
void writeObjectToConnection(Connection& con, const Object& obj) {
std::array<char, 100> data = Object::serialize(obj);
con.writeNext(data);
}
template<typename Object, typename Connection>
Object readObjectFromConnection(Connection& con) {
std::array<char, 100> data = con.readNext();
return Object::deserialize(data);
}
std::cout << “serialize first user account” << std::endl;
UserAccount firstAccount;
TcpConnection tcpConnection;
writeObjectToConnection(tcpConnection, firstAccount);
UserAccount transmittedFirstAccount = readObjectFromConnection<UserAccount>(tcpConnection);
std::cout << “serialize second user account” << std::endl;
UserAccount secondAccount;
UdpConnection udpConnection;
writeObjectToConnection(udpConnection, secondAccount);
UserAccount transmittedSecondAccount = readObjectFromConnection<UserAccount>(udpConnection);
The output of the program is as follows:
serialize first user account
the user account has been serialized
the data has been written
the data has been read
the user account has been deserialized
serialize second user account
the user account has been serialized
the data has been written
the data has been read
the user account has been deserialized
#include <currency.h>
#include <iostream>
template<typename Currency>
class Account {
public:
Account(Currency amount) : balance(amount) {}
Currency getBalance() const {
return balance;
}
private:
Currency balance;
};
template<typename OtherCurrency>
void addToBalance(OtherCurrency amount) {
balance.d_value += to<Currency>(amount).d_value;
}
Account<GBP> gbpAccount(GBP(1000));
// Add different currencies
std::cout << “Balance: “ << gbpAccount.getBalance().d_value << “ (GBP)” << std::endl;
gbpAccount.addToBalance(EUR(100));
std::cout << “+100 (EUR)” << std::endl;
std::cout << “Balance: “ << gbpAccount.getBalance().d_value << “ (GBP)” << std::endl;
The output of the program is:
Balance: 1000 (GBP)
+100 (EUR)
Balance: 1089 (GBP)
#include <array>
template<typename T, int R, int C>
class Matrix {
// We store row_1, row_2, ..., row_C
std::array<T, R*C> data;
public:
Matrix() : data({}) {}
Matrix(std::array<T, R*C> initialValues) : data(initialValues) {}
};
T& get(int row, int col) {
if (row >= R || col >= C) {
std::abort();
}
return data[row*C + col];
}
template<typename T, size_t R, size_t C>
std::ostream& operator<<(std::ostream& os, Matrix<T, R, C> matrix) {
os << ‘ ’;
for(int r=0; r < R; r++) {
for(int c=0; c < C; c++) {
os << matrix.get(r, c) << ‘ ‘;
}
os << “ ”;
}
return os;
}
Matrix<int, 3, 2> matrix({
1, 2,
3, 4,
5, 6
});
std::cout << “Initial matrix:” << matrix << std::endl;
matrix.get(1, 1) = 7;
std::cout << “Modified matrix:” << matrix << std::endl;
The output is as follows:
Initial matrix:
1 2
3 4
5 6
Modified matrix:
1 2
3 7
5 6
The function returns an array of the same type, but length R.
std::array<T, R> multiply(const std::array<T, C>& vector){
std::array<T, R> result = {};
for(size_t r = 0; r < R; r++) {
for(size_t c = 0; c < C; c++) {
result[r] += get(r, c) * vector[c];
}
}
return result;
}
std::array<int, 2> vector = {8, 9};
std::array<int, 3> result = matrix.multiply(vector);
std::cout << “Result of multiplication: [“ << result[0] << “, “
<< result[1] << “, “ << result[2] << “]” << std::endl;
The output is as follows:
Result of multiplication: [26, 87, 94]
#include <functional>
template<int R, int C, typename T = int, typename Multiply=std::multiplies<T> >
class Matrix {
std::array<T, R*C> data;
Multiply multiplier;
public:
Matrix() : data({}), multiplier() {}
Matrix(std::array<T, R*C> initialValues) : data(initialValues), multiplier() {}
};
The get() function remains the same as the previous activity.
std::array<T, R> multiply(const std::array<T, C>& vector) {
std::array<T, R> result = {};
for(int r = 0; r < R; r++) {
for(int c = 0; c < C; c++) {
result[r] += multiplier(get(r, c), vector[c]);
}
}
return result;
}
// Create a matrix of int, with the ‘plus’ operation by default
Matrix<3, 2, int, std::plus<int>> matrixAdd({
1, 2,
3, 4,
5, 6
});
std::array<int, 2> vector = {8, 9};
// This will call std::plus when doing the multiplication
std::array<int, 3> result = matrixAdd.multiply(vector);
std::cout << “Result of multiplication(with +): [“ << result[0] << “, “
<< result[1] << “, “ << result[2] << “]” << std::endl;
The output is as follows:
Result of multiplication(with +): [20, 24, 28]
template<typename Action, typename Parameter>
void execute_on_user_cart(UserIdentifier user, Action action, Parameter&& parameter) {
if(isLoggedIn(user)) {
Cart cart = getUserCart(user);
action(cart, std::forward<Parameter>(parameter));
} else {
std::cout << “The user is not logged in” << std::endl;
}
}
Item toothbrush{1023};
Item toothpaste{1024};
UserIdentifier loggedInUser{0};
std::cout << “Adding items if the user is logged in” << std::endl;
execute_on_user_cart(loggedInUser, addItems, std::vector<Item>({toothbrush, toothpaste}));
UserIdentifier loggedOutUser{1};
std::cout << “Removing item if the user is logged in” << std::endl;
execute_on_user_cart(loggedOutUser, removeItem, toothbrush);
The output is as follows:
Adding items if the user is logged in
Items added
Removing item if the user is logged in
The user is not logged in
template<typename Action, typename... Parameters>
void execute_on_user_cart(UserIdentifier user, Action action, Parameters&&... parameters) {
if(isLoggedIn(user)) {
Cart cart = getUserCart(user);
action(cart, std::forward<Parameters>(parameters)...);
} else {
std::cout << “The user is not logged in” << std::endl;
}
}
Item toothbrush{1023};
Item apples{1024};
UserIdentifier loggedInUser{0};
std::cout << “Replace items if the user is logged in” << std::endl;
execute_on_user_cart(loggedInUser, replaceItem, toothbrush, apples);
UserIdentifier loggedOutUser{1};
std::cout << “Replace item if the user is logged in” << std::endl;
execute_on_user_cart(loggedOutUser, removeItem, toothbrush);
The output is as follows:
Replace items if the user is logged in
Replacing item
Item removed
Items added
Replace item if the user is logged in
The user is not logged in
#include <array>
array<int,10> balances;
for (int i=0; i < balances.size(); ++i)
{
balances[i] = 0;
}
balances.front() += 100;
balances.back() += 100;
We would like to store the account balance of an arbitrary number of users. We then want to add 100 users to the account list, with a balance of 500.
#include <vector>
std::vector<int> balances;
balances.reserve(100);
for (int i=0; i<100; ++i)
{
balances.push_back(500);
}
#include <map>
#include <string>
std::map<std::string, int> balances;
balances.insert(std::make_pair(“Alice”,50));
balances.insert(std::make_pair(“Bob”, 50));
balances.insert(std::make_pair(“Charlie”, 50));
auto donaldAccountPos = balances.find(“Donald”);
bool hasAccount = (donaldAccountPos != balances.end());
std::cout << “Donald has an account: “ << hasAccount << std::endl;
auto alicePosition = balances.find(“Alice”);
std::cout << “Alice balance is: “ << alicePosition->second << std::endl;
#include <stack>
std::stack<RegistrationForm> registrationForms;
stack.push(form);
std::cout << “Pushed form for user “ << form.userName << std::endl;
while(not stack.empty()) {
processRegistration(stack.top());
stack.pop();
}
int main(){
std::stack<RegistrationForm> registrationForms;
storeRegistrationForm(registrationForms, RegistrationForm{“Alice”});
storeRegistrationForm(registrationForms, RegistrationForm{“Bob”});
storeRegistrationForm(registrationForms, RegistrationForm{“Charlie”});
endOfDayRegistrationProcessing(registrationForms);
}
#include <variant>
class Airplane {
std::variant<AtGate, Taxi, Flying> state;
public:
Airplane(int gate) : state(AtGate{gate}) {
std::cout << “At gate “ << gate << std::endl;
}
};
void startTaxi(int lane, int numPassengers) {
if (not std::holds_alternative<AtGate>(state)) {
std::cout << “Not at gate: the plane cannot start taxi to lane “ << lane << std::endl;
return;
}
std::cout << “Taxing to lane “ << lane << std::endl;
state = Taxi{lane, numPassengers};
}
void takeOff(float speed) {
if (not std::holds_alternative<Taxi>(state)) {
std::cout << “Not at lane: the plane cannot take off with speed “ << speed << std::endl;
return;
}
std::cout << “Taking off at speed “ << speed << std::endl;
state = Flying{speed};
}
class AirplaneStateVisitor {
public:
void operator()(const AtGate& atGate) {
std::cout << “AtGate: “ << atGate.gate << std::endl;
}
void operator()(const Taxi& taxi) {
std::cout << “Taxi: lane “ << taxi.lane << “ with “ << taxi.numPassengers << “ passengers” << std::endl;
}
void operator()(const Flying& flying) {
std::cout << “Flaying: speed “ << flying.speed << std::endl;
}
};
void currentStatus() {
AirplaneStateVisitor visitor;
std::visit(visitor, state);
}
int main()
{
Airplane airplane(52);
airplane.currentStatus();
airplane.startTaxi(12, 250);
airplane.currentStatus();
airplane.startTaxi(13, 250);
airplane.currentStatus();
airplane.takeOff(800);
airplane.currentStatus();
airplane.takeOff(900);
}
class Character {
public:
void moveTo(Position newPosition) {
position = newPosition;
std::cout << “Moved to position “ << newPosition.positionIdentifier << std::endl;
}
private:
Position position;
};
struct Position {
// Fields to describe the position go here
std::string positionIdentifier;
};
// Hero inherits publicly from Character: it has
// all the public member of the Character class.
class Hero : public Character {
};
// Enemy inherits publicly from Character, like Hero
class Enemy : public Character {
};
class Spell {
public:
Spell(std::string name) : d_name(name) {}
std::string name() const {
return d_name;
}
private:
std::string d_name;
};
public:
void cast(Spell spell) {
// Cast the spell
std::cout << “Casting spell “ << spell.name() << std::endl;
}
public:
void swingSword() {
// Swing the sword
std::cout << “Swinging sword” << std::endl;
}
int main()
{
Position position{“Enemy castle”};
Hero hero;
Enemy enemy;
// We call moveTo on Hero, which calls the method inherited
// from the Character class
hero.moveTo(position);
enemy.moveTo(position);
// We can still use the Hero and Enemy methods
hero.cast(Spell(“fireball”));
enemy.swingSword();
}
class Employee {
public:
virtual int getBaseSalary() const { return 100; }
virtual int getBonus(const Deparment& dep) const {
if (dep.hasReachedTarget()) {
}
return 0;
}
int getTotalComp(const Deparment& dep) {
}
};
class Manager : public Employee {
public:
virtual int getBaseSalary() const override { return 150; }
virtual int getBonus(const Deparment& dep) const override {
if (dep.hasReachedTarget()) {
int additionalDeparmentEarnings = dep.effectiveEarning() - dep.espectedEarning();
return 0.2 * getBaseSalary() + 0.01 * additionalDeparmentEarnings;
}
return 0;
}
};
class Department {
public:
bool hasReachedTarget() const {return true;}
int espectedEarning() const {return 1000;}
int effectiveEarning() const {return 1100;}
};
int main()
{
Department dep;
Employee employee;
Manager manager;
std::cout << “Employee: “ << employee.getTotalComp(dep) << “. Manager: “ << manager.getTotalComp(dep) << std::endl;
}
struct UserProfile {};
struct UserId {};
class UserProfileStorage {
public:
virtual UserProfile getUserProfile(const UserId& id) const = 0;
virtual ~UserProfileStorage() = default;
protected:
UserProfileStorage() = default;
UserProfileStorage(const UserProfileStorage&) = default;
UserProfileStorage& operator=(const UserProfileStorage&) = default;
};
class UserProfileCache : public UserProfileStorage {
public:
UserProfile getUserProfile(const UserId& id) const override {
std::cout << “Getting the user profile from the cache” << std::endl;
return UserProfile(); }
};
void exampleOfUsage(const UserProfileStorage& storage) {
UserId user;
std::cout << “About to retrieve the user profile from the storage” <<std::endl;
UserProfile userProfile = storage.getUserProfile(user);
}
int main()
{
UserProfileCache cache;
exampleOfUsage (cache);
}
#include <iostream>
#include <memory>
#include <userprofile_activity18.h>
class UserProfileStorageFactory {
public:
std::unique_ptr<UserProfileStorage> create() const {
return std::make_unique<UserProfileCache>();
}
};
void getUserProfile(const UserProfileStorageFactory& storageFactory) {
std::unique_ptr<UserProfileStorage> storage = storageFactory.create();
UserId user;
storage->getUserProfile(user);
// The storage is automatically destroyed
}
int main()
{
UserProfileStorageFactory factory;
getUserProfile(factory);
#include <future>
struct DatabaseConnection {};
void updateOrderList(DatabaseConnection&) {}
void scheduleOrderProcessing(DatabaseConnection&) {}
/* We need to get a copy of the shared_ptr so it stays alive until this function finishes */
void updateWithConnection(std::shared_ptr<DatabaseConnection> connection) {
updateOrderList(*connection);
}
There are several users of the connection, and we do not know which one is the owner, since the connection needs to stay alive as long as anyone is using it.
/* We need to get a copy of the shared_ptr so it stays alive until this function finishes. */
void scheduleWithConnection(std::shared_ptr<DatabaseConnection> connection) {
scheduleOrderProcessing(*connection);
}
int main()
{
std::shared_ptr<DatabaseConnection> connection = std::make_shared<DatabaseConnection>();
std::async(std::launch::async, updateWithConnection, connection);
std::async(std::launch::async, scheduleWithConnection, connection);
}