Add initial implementation of Easyfind, Span, and MutantStack classes with tests

This commit is contained in:
whaffman 2025-08-20 13:12:22 +02:00
parent 2f64f3327f
commit 8c34d8e696
17 changed files with 640 additions and 1 deletions

6
.gitignore vendored
View File

@ -0,0 +1,6 @@
*.d
*.o
.cache
Easyfind
Span
MutantStack

View File

@ -15,7 +15,7 @@ VPATH = src
SRC = $(notdir $(wildcard src/*.cpp))
OBJ = $(SRC:.cpp=.o)
CC = c++
CFLAGS = -Wall -Wextra -Werror -std=c++11 -MMD
CFLAGS = -Wall -Wextra -Werror -std=c++23 -MMD
all: $(NAME)

2
ex00/Makefile Normal file
View File

@ -0,0 +1,2 @@
NAME := Easyfind
include ../common.mk

View File

@ -0,0 +1,19 @@
[
{
"arguments": [
"/usr/bin/c++",
"-Wall",
"-Wextra",
"-Werror",
"-std=c++23",
"-I./inc",
"-c",
"-o",
"main.o",
"src/main.cpp"
],
"directory": "/home/willem/projects/CPP08/ex00",
"file": "/home/willem/projects/CPP08/ex00/src/main.cpp",
"output": "/home/willem/projects/CPP08/ex00/main.o"
}
]

18
ex00/inc/easyfind.hpp Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <algorithm>
#include <stdexcept>
template <typename T>
int &easyfind(T &container, int value)
{
typename T::iterator it = std::find(container.begin(), container.end(), value);
if (it != container.end())
{
return *it;
}
else
{
throw std::out_of_range("Value not found");
}
}

3
ex00/inc/easyfind.tpp Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include "easyfind.hpp"

86
ex00/src/main.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "easyfind.hpp"
#include <deque>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec = {1, 2, 3, 4, 5};
try
{
std::cout << "Testing with vector...\n";
std::cout << "Vector contents: ";
for (const auto &val : vec)
{
std::cout << val << " ";
}
std::cout << "\n";
std::cout << "Searching for value 3...\n";
int &found = easyfind(vec, 3);
std::cout << "Found: " << found << std::endl;
std::cout << "Modifying found value...\n";
found = 10; // Modify the found value
for (const auto &val : vec)
{
std::cout << val << " ";
}
std::cout << "\n";
}
catch (const std::out_of_range &e)
{
std::cerr << e.what() << std::endl;
}
try
{
std::cout << "Searching for value 6 (not in vector)...\n";
int &notFound = easyfind(vec, 6);
std::cout << "Found: " << notFound << std::endl;
}
catch (const std::out_of_range &e)
{
std::cerr << e.what() << std::endl;
}
std::cout << "\n\nTesting with deque...\n";
std::deque<int> deq = {10, 20, 30, 40, 50};
try
{
std::cout << "Deque contents: ";
for (const auto &val : deq)
{
std::cout << val << " ";
}
std::cout << "\n";
std::cout << "Searching for value 30...\n";
int &foundInDeque = easyfind(deq, 30);
std::cout << "Found: " << foundInDeque << "\n";
std::cout << "Modifying found value...\n";
foundInDeque = 100; // Modify the found value
for (const auto &val : deq)
{
std::cout << val << " ";
}
std::cout << "\n";
}
catch (const std::out_of_range &e)
{
std::cerr << e.what() << std::endl;
}
try
{
std::cout << "Searching for value 60 (not in deque)...\n";
int &notFoundInDeque = easyfind(deq, 60);
std::cout << "Found: " << notFoundInDeque << std::endl;
}
catch (const std::out_of_range &e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}

2
ex01/Makefile Normal file
View File

@ -0,0 +1,2 @@
NAME := Span
include ../common.mk

View File

@ -0,0 +1,19 @@
[
{
"arguments": [
"/usr/bin/c++",
"-Wall",
"-Wextra",
"-Werror",
"-std=c++23",
"-I./inc",
"-c",
"-o",
"main.o",
"src/main.cpp"
],
"directory": "/home/willem/projects/CPP08/ex01",
"file": "/home/willem/projects/CPP08/ex01/src/main.cpp",
"output": "/home/willem/projects/CPP08/ex01/main.o"
}
]

49
ex01/inc/Span.hpp Normal file
View File

@ -0,0 +1,49 @@
#pragma once
#include <concepts>
#include <exception>
#include <iterator>
#include <vector>
class Span
{
public:
Span() = delete;
Span(unsigned int size);
Span(const Span &other);
Span(Span &&other) noexcept;
Span &operator=(const Span &other);
Span &&operator=(Span &&other) noexcept;
~Span() noexcept;
void addNumber(int number);
unsigned int shortestSpan() const;
unsigned int longestSpan() const;
template <std::input_iterator Iterator>
requires std::same_as<std::iter_value_t<Iterator>, int>
void addRange(Iterator begin, Iterator end)
{
for (Iterator it = begin; it < end; it++)
{
addNumber(*it);
}
}
class OutOfSpaceException : public std::exception
{
public:
const char *what() const throw();
};
class NoSpanFoundException : public std::exception
{
public:
const char *what() const throw();
};
private:
unsigned int _size;
std::vector<int> _data;
};

100
ex01/src/Span.cpp Normal file
View File

@ -0,0 +1,100 @@
#include "Span.hpp"
#include <algorithm>
#include <limits>
#include <vector>
Span::Span(unsigned int size) : _size(size), _data() {
_data.reserve(size);
}
Span::Span(const Span &other) : _size(other._size), _data(other._size)
{
for (int n : other._data)
{
addNumber(n);
}
}
Span::Span(Span &&other) noexcept : _size(other._size), _data(std::move(other._data))
{
other._size = 0;
}
Span &Span::operator=(const Span &other)
{
if (this != &other)
{
_size = other._size;
_data = other._data;
}
return *this;
}
Span &&Span::operator=(Span &&other)
{
if (this != &other)
{
_size = other._size;
_data = std::move(other._data);
other._size = 0;
}
return std::move(*this);
}
Span::~Span() {}
void Span::addNumber(int number)
{
if (_data.size() >= _size)
{
throw OutOfSpaceException();
}
_data.push_back(number);
}
unsigned int Span::shortestSpan() const
{
if (_data.size() < 2)
{
throw NoSpanFoundException();
}
std::vector<int> sortedData = _data;
std::sort(sortedData.begin(), sortedData.end());
unsigned int minSpan = std::numeric_limits<int>::max();
for (size_t i = 0; i < sortedData.size() - 1; i++)
{
unsigned int span = sortedData[i + 1] - sortedData[i];
if (span < minSpan)
{
minSpan = span;
}
}
return minSpan;
}
unsigned int Span::longestSpan() const
{
if (_data.size() < 2)
{
throw NoSpanFoundException();
}
auto min = std::min_element(_data.begin(), _data.end());
auto max = std::max_element(_data.begin(), _data.end());
return *max - *min;
}
const char *Span::OutOfSpaceException::what() const throw()
{
return "No more space to add numbers";
}
const char *Span::NoSpanFoundException::what() const throw()
{
return "No span found, not enough numbers";
}

131
ex01/src/main.cpp Normal file
View File

@ -0,0 +1,131 @@
#include "Span.hpp"
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <print>
#define GUB "\033[1;32;4m"
#define ERROR "\033[1;31m"
#define END "\033[0m"
std::vector<int> generateRandomVecor(int size)
{
std::vector<int> vec;
std::srand(static_cast<unsigned int>(std::time(nullptr)));
for (int i = 0; i < size; ++i)
{
vec.push_back(rand());
}
return vec;
}
int main()
{
std::println(GUB "Testing Span with more numbers then the size of the span..." END);
try
{
std::println("Creating Span with size 5...");
Span span(5);
std::println("Adding 6 numbers to the span...");
span.addNumber(1);
span.addNumber(2);
span.addNumber(3);
span.addNumber(4);
span.addNumber(5);
span.addNumber(6); // This should throw an exception
}
catch (const Span::OutOfSpaceException &e)
{
std::println(std::cerr, ERROR "Error: {}" END, e.what());
}
std::println();
std::println(GUB "Testing Span with 0 numbers..." END);
try
{
std::println("Creating Span with size 0...");
Span span(0);
std::println("Trying to find the shortest span...");
span.shortestSpan(); // This should throw an exception
}
catch (const Span::NoSpanFoundException &e)
{
std::println(std::cerr, ERROR "Error: {}" END, e.what());
}
std::println();
std::println(GUB "Testing Span with one number..." END);
try
{
std::println("Creating Span with size 1...");
Span span(1);
std::println("Adding 1 number to the span...");
span.addNumber(42);
std::println("Trying to find the shortest span...");
span.shortestSpan(); // This should throw an exception
}
catch (const Span::NoSpanFoundException &e)
{
std::println(std::cerr, ERROR "Error: {}" END, e.what());
}
std::println();
std::println(GUB "Testing Span with two numbers..." END);
try
{
std::println("Creating Span with size 2...");
Span span(2);
std::println("Adding 2 numbers to the span...");
span.addNumber(10);
span.addNumber(20);
std::println("Trying to find the shortest span...");
unsigned int shortest = span.shortestSpan();
std::println("Shortest span: {}", shortest);
std::println("Finding the longest span...");
unsigned int longest = span.longestSpan();
std::println("Longest span: {}", longest);
}
catch (const Span::NoSpanFoundException &e)
{
std::println(std::cerr, ERROR "Error: {}" END, e.what());
}
catch (const Span::OutOfSpaceException &e)
{
std::println(std::cerr, ERROR "Error: {}" END, e.what());
}
std::println();
std::println(GUB "Testing Span with a range of random numbers..." END);
try
{
unsigned int size = 10'000;
std::println("Generating a vector with {} random numbers...", size);
std::vector<int> randomNumbers = generateRandomVecor(size);
std::println("Adding the random numbers to a span of size {}...", size);
Span span(size);
span.addRange(randomNumbers.begin(), randomNumbers.end());
std::println("Finding the shortest span...");
unsigned int shortest = span.shortestSpan();
std::println("Shortest span: {}", shortest);
std::println("Finding the longest span...");
unsigned int longest = span.longestSpan();
std::println("Longest span: {}", longest);
}
catch (const Span::OutOfSpaceException &e)
{
std::println(std::cerr, ERROR "Error: {}" END, e.what());
}
catch (const Span::NoSpanFoundException &e)
{
std::println(std::cerr, ERROR "Error: {}" END, e.what());
}
return 0;
}

2
ex02/Makefile Normal file
View File

@ -0,0 +1,2 @@
NAME := MutantStack
include ../common.mk

View File

@ -0,0 +1,36 @@
[
{
"arguments": [
"/usr/bin/c++",
"-Wall",
"-Wextra",
"-Werror",
"-std=c++23",
"-I./inc",
"-c",
"-o",
"main.o",
"src/main.cpp"
],
"directory": "/home/willem/projects/CPP08/ex02",
"file": "/home/willem/projects/CPP08/ex02/src/main.cpp",
"output": "/home/willem/projects/CPP08/ex02/main.o"
},
{
"arguments": [
"/usr/bin/c++",
"-Wall",
"-Wextra",
"-Werror",
"-std=c++23",
"-I./inc",
"-c",
"-o",
"MutantStack.o",
"src/MutantStack.cpp"
],
"directory": "/home/willem/projects/CPP08/ex02",
"file": "/home/willem/projects/CPP08/ex02/src/MutantStack.cpp",
"output": "/home/willem/projects/CPP08/ex02/MutantStack.o"
}
]

24
ex02/inc/MutantStack.hpp Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include <stack>
template <typename T>
class MutantStack : public std::stack<T>
{
public:
MutantStack();
MutantStack(const MutantStack &other);
MutantStack(MutantStack &&other) noexcept;
MutantStack &operator=(const MutantStack &other);
MutantStack &&operator=(MutantStack &&other) noexcept;
~MutantStack() noexcept;
typedef typename std::stack<T>::container_type::iterator iterator;
typedef typename std::stack<T>::container_type::const_iterator const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
};
#include "MutantStack.tpp"

63
ex02/inc/MutantStack.tpp Normal file
View File

@ -0,0 +1,63 @@
#pragma once
#include "MutantStack.hpp"
template <typename T>
MutantStack<T>::MutantStack() : std::stack<T>()
{}
template <typename T>
MutantStack<T>::MutantStack(const MutantStack &other) : std::stack<T>(other)
{}
template <typename T>
MutantStack<T>::MutantStack(MutantStack &&other) noexcept : std::stack<T>(std::move(other))
{}
template <typename T>
MutantStack<T> &MutantStack<T>::operator=(const MutantStack &other)
{
if (this != &other)
{
std::stack<T>::operator=(other);
}
return *this;
}
template <typename T>
MutantStack<T> &&MutantStack<T>::operator=(MutantStack &&other) noexcept
{
if (this != &other)
{
std::stack<T>::operator=(std::move(other));
}
return std::move(*this);
}
template <typename T>
MutantStack<T>::~MutantStack() noexcept
{}
template <typename T>
typename MutantStack<T>::iterator MutantStack<T>::begin()
{
return this->c.begin();
}
template <typename T>
typename MutantStack<T>::iterator MutantStack<T>::end()
{
return this->c.end();
}
template <typename T>
typename MutantStack<T>::const_iterator MutantStack<T>::begin() const
{
return this->c.begin();
}
template <typename T>
typename MutantStack<T>::const_iterator MutantStack<T>::end() const
{
return this->c.end();
}

79
ex02/src/main.cpp Normal file
View File

@ -0,0 +1,79 @@
#include "MutantStack.hpp"
#include <iostream>
#include <print>
#define INFO "\n\033[1;32;4m"
#define ERROR "\033[1;31m"
#define END "\033[0m"
int main()
{
std::println(INFO "Testing MutantStack..." END);
std::println(INFO "Creating a MutantStack of integers..." END);
MutantStack<int> mutantStack;
mutantStack.push(1);
mutantStack.push(2);
mutantStack.push(3);
std::println("MutantStack created with elements: 1, 2, 3");
std::println("The size of MutantStack is: {}", mutantStack.size());
std::println("Pop the top element: {}", mutantStack.top());
mutantStack.pop();
std::println("The size of MutantStack after pop is: {}", mutantStack.size());
std::println(INFO "Testing Copy constructor..." END);
MutantStack<int> copyStack(mutantStack);
std::println("Copy constructor called.");
std::println("The size of the copied MutantStack is: {}", copyStack.size());
std::println("The elements of the copied MutantStack are: ");
for (MutantStack<int>::iterator it = copyStack.begin(); it != copyStack.end(); ++it)
{
std::println(" - {}", *it);
}
std::println(INFO "Testing the Copy assignment operator..." END);
MutantStack<int> assignStack;
assignStack = copyStack;
std::println("Copy assignment operator called.");
std::println("The size of the assigned MutantStack is: {}", assignStack.size());
std::println("The elements of the assigned MutantStack are: ");
for (MutantStack<int>::iterator it = assignStack.begin(); it != assignStack.end(); ++it)
{
std::println(" - {}", *it);
}
std::println(INFO "Testing Move constructor..." END);
MutantStack<int> moveStack(std::move(mutantStack));
std::println("Move constructor called.");
std::println("The size of the moved MutantStack is: {}", moveStack.size());
std::println("The elements of the moved MutantStack are: ");
for (MutantStack<int>::iterator it = moveStack.begin(); it != moveStack.end(); ++it)
{
std::println(" - {}", *it);
}
std::println(INFO "Testing Move assignment operator..." END);
MutantStack<int> moveAssignStack;
moveAssignStack = std::move(moveStack);
std::println("Move assignment operator called.");
std::println("The size of the assigned MutantStack is: {}", moveAssignStack.size());
std::println("The elements of the assigned MutantStack are: ");
for (MutantStack<int>::iterator it = moveAssignStack.begin(); it != moveAssignStack.end(); ++it)
{
std::println(" - {}", *it);
}
std::println(INFO "Testing MutantStack with const iterators..." END);
MutantStack<int> constStack;
constStack.push(1);
constStack.push(2);
constStack.push(3);
std::println("Const MutantStack created with elements: 1, 2, 3");
std::println("The size of Const MutantStack is: {}", constStack.size());
std::println("Pop the top element: {}", constStack.top());
constStack.pop();
std::println("The size of Const MutantStack after pop is: {}", constStack.size());
std::println("The elements of the Const MutantStack are: ");
for (MutantStack<int>::const_iterator it = constStack.begin(); it != constStack.end(); ++it)
{
std::println(" - {}", *it);
}
}