aboutsummaryrefslogtreecommitdiff
path: root/week08
diff options
context:
space:
mode:
Diffstat (limited to 'week08')
-rw-r--r--week08/Exercise1.cpp80
-rw-r--r--week08/Exercise1.h20
-rw-r--r--week08/Exercise2.cpp160
-rw-r--r--week08/Exercise2.h22
-rw-r--r--week08/Exercise3.hpp5
-rw-r--r--week08/Exercise4.cpp141
-rw-r--r--week08/Exercise4.h37
-rw-r--r--week08/Exercise5.hpp203
-rw-r--r--week08/Exercise6.cpp27
-rw-r--r--week08/Exercise6.h7
-rw-r--r--week08/Exercise7.cpp97
-rw-r--r--week08/Exercise7.h33
-rw-r--r--week08/README.md153
13 files changed, 985 insertions, 0 deletions
diff --git a/week08/Exercise1.cpp b/week08/Exercise1.cpp
new file mode 100644
index 0000000..0686a2c
--- /dev/null
+++ b/week08/Exercise1.cpp
@@ -0,0 +1,80 @@
+#include "Exercise1.h"
+#include <cstring>
+
+void StreetList::free() {
+ for (int i = 0; i < lastUnused; i++) {
+ delete[] streetNames[i];
+ }
+ delete[] streetNames;
+}
+
+void StreetList::copyFrom(const StreetList& other) {
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+
+ this->streetNames = new char*[allocated];
+ for (int i = 0; i < lastUnused; i++) {
+ this->streetNames[i] = new char[strlen(other.streetNames[i]) + 1];
+ strcpy(this->streetNames[i], other.streetNames[i]);
+ }
+}
+
+void StreetList::resize() {
+ allocated *= 2;
+ char** biggerList = new char*[allocated];
+ for (int i = 0; i < lastUnused; i++) {
+ // Понеже са указатели в динамичната памет, можем да си спестим new char[] и strcpy
+ biggerList[i] = streetNames[i];
+ }
+ delete[] streetNames;
+ streetNames = biggerList;
+}
+
+StreetList::StreetList() {
+ streetNames = nullptr;
+ lastUnused = allocated = 0;
+}
+
+StreetList::~StreetList() {
+ free();
+}
+
+StreetList::StreetList(const StreetList& other) {
+ copyFrom(other);
+}
+
+StreetList& StreetList::operator=(const StreetList& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+StreetList::StreetList(StreetList&& other) {
+ this->streetNames = other.streetNames;
+ other.streetNames = nullptr;
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+}
+
+StreetList& StreetList::operator=(StreetList&& other) {
+ if (this != &other) {
+ free();
+
+ this->streetNames = other.streetNames;
+ other.streetNames = nullptr;
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+ }
+ return *this;
+}
+
+void StreetList::Add(const char* newString) {
+ if (lastUnused == allocated) {
+ resize();
+ }
+ streetNames[lastUnused] = new char[strlen(newString) + 1];
+ strcpy(streetNames[lastUnused], newString);
+ lastUnused++;
+}
diff --git a/week08/Exercise1.h b/week08/Exercise1.h
new file mode 100644
index 0000000..1bd91d7
--- /dev/null
+++ b/week08/Exercise1.h
@@ -0,0 +1,20 @@
+class StreetList {
+ char **streetNames; // динамично-заделен масив от динамично-заделени низове
+ int lastUnused;
+ int allocated;
+
+ void free();
+ void copyFrom(const StreetList& other);
+
+ void resize();
+
+public:
+ StreetList();
+ ~StreetList();
+ StreetList(const StreetList& other);
+ StreetList& operator=(const StreetList& other);
+ StreetList(StreetList&& other);
+ StreetList& operator=(StreetList&& other);
+
+ void Add(const char* newString);
+};
diff --git a/week08/Exercise2.cpp b/week08/Exercise2.cpp
new file mode 100644
index 0000000..6fe9800
--- /dev/null
+++ b/week08/Exercise2.cpp
@@ -0,0 +1,160 @@
+#include "Exercise2.h"
+#include <cstring>
+#include <fstream>
+
+void Person::free() {
+ delete[] firstName;
+ delete[] middleName;
+ delete[] lastName;
+}
+
+void Person::copyFrom(const Person& other) {
+ this->firstName = new char[strlen(other.firstName) + 1];
+ strcpy(this->firstName, other.firstName);
+ this->middleName = new char[strlen(other.middleName) + 1];
+ strcpy(this->middleName, other.middleName);
+ this->lastName = new char[strlen(other.lastName) + 1];
+ strcpy(this->lastName, other.lastName);
+
+ this->id = other.id;
+}
+
+Person::Person() {
+ firstName = middleName = lastName = nullptr;
+ id = 0;
+}
+
+Person::~Person() {
+ free();
+}
+
+Person::Person(const Person& other) {
+ copyFrom(other);
+}
+
+Person& Person::operator=(const Person& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+Person::Person(Person&& other) {
+ this->firstName = other.firstName;
+ this->middleName = other.middleName;
+ this->lastName = other.lastName;
+ other.firstName = other.middleName = other.lastName = nullptr;
+
+ this->id = other.id;
+}
+
+Person& Person::operator=(Person&& other) {
+ if (this != &other) {
+ free();
+
+ this->firstName = other.firstName;
+ this->middleName = other.middleName;
+ this->lastName = other.lastName;
+ other.firstName = other.middleName = other.lastName = nullptr;
+
+ this->id = other.id;
+ }
+ return *this;
+}
+
+void Person::SaveText(const char* outFileName) {
+ std::ofstream outFile(outFileName);
+ if (!outFile.is_open()) {
+ throw "Couldn't open file!";
+ }
+
+ outFile << firstName << '\n';
+ outFile << middleName << '\n';
+ outFile << lastName << '\n';
+ outFile << id << '\n';
+
+ outFile.close();
+}
+
+void Person::LoadText(const char* inFileName) {
+ std::ifstream inFile(inFileName);
+ if (!inFile.is_open()) {
+ throw "Couldn't open file!";
+ }
+
+ free();
+
+ char buffer[1024];
+
+ inFile.getline(buffer, 1024);
+ firstName = new char[strlen(buffer) + 1];
+ strcpy(firstName, buffer);
+
+ inFile.getline(buffer, 1024);
+ middleName = new char[strlen(buffer) + 1];
+ strcpy(middleName, buffer);
+
+ inFile.getline(buffer, 1024);
+ lastName = new char[strlen(buffer) + 1];
+ strcpy(lastName, buffer);
+
+ inFile >> id;
+
+ inFile.close();
+}
+
+void Person::SaveBinary(const char* outFileName) {
+ std::ofstream outFile(outFileName, std::ios::binary);
+ if (!outFile.is_open()) {
+ throw "Couldn't open file!";
+ }
+
+ int firstNameLen = strlen(firstName);
+ int middleNameLen = strlen(middleName);
+ int lastNameLen = strlen(lastName);
+
+ outFile.write((const char*)&firstNameLen, sizeof(firstNameLen));
+ outFile.write(firstName, sizeof(char) * firstNameLen);
+
+ outFile.write((const char*)&middleNameLen, sizeof(middleNameLen));
+ outFile.write(middleName, sizeof(char) * middleNameLen);
+
+ outFile.write((const char*)&lastNameLen, sizeof(lastNameLen));
+ outFile.write(lastName, sizeof(char) * lastNameLen);
+
+ outFile.write((const char*)&id, sizeof(id));
+
+ outFile.close();
+}
+
+void Person::LoadBinary(const char* inFileName) {
+ std::ifstream inFile(inFileName, std::ios::binary);
+ if (!inFile.is_open()) {
+ throw "Couldn't open file!";
+ }
+
+ free();
+
+
+ int currentLength;
+
+ inFile.read((char*)&currentLength, sizeof(currentLength));
+ firstName = new char[currentLength + 1];
+ inFile.read(firstName, sizeof(char) * currentLength);
+ firstName[currentLength] = '\0';
+
+ inFile.read((char*)&currentLength, sizeof(currentLength));
+ middleName = new char[currentLength + 1];
+ inFile.read(middleName, sizeof(char) * currentLength);
+ middleName[currentLength] = '\0';
+
+ inFile.read((char*)&currentLength, sizeof(currentLength));
+ lastName = new char[currentLength + 1];
+ inFile.read(lastName, sizeof(char) * currentLength);
+ lastName[currentLength] = '\0';
+
+ inFile.read((char*)&id, sizeof(id));
+
+ inFile.close();
+}
diff --git a/week08/Exercise2.h b/week08/Exercise2.h
new file mode 100644
index 0000000..7a9e6e2
--- /dev/null
+++ b/week08/Exercise2.h
@@ -0,0 +1,22 @@
+class Person {
+ char* firstName;
+ char* middleName;
+ char* lastName;
+ unsigned id;
+
+ void free();
+ void copyFrom(const Person& other);
+
+public:
+ Person();
+ ~Person();
+ Person(const Person& other);
+ Person& operator=(const Person& other);
+ Person(Person&& other);
+ Person& operator=(Person&& other);
+
+ void SaveText(const char* outFileName);
+ void LoadText(const char* inFileName);
+ void SaveBinary(const char* outFileName);
+ void LoadBinary(const char* inFileName);
+};
diff --git a/week08/Exercise3.hpp b/week08/Exercise3.hpp
new file mode 100644
index 0000000..9b15db2
--- /dev/null
+++ b/week08/Exercise3.hpp
@@ -0,0 +1,5 @@
+template <class T, class P>
+struct Pair {
+ T left;
+ P right;
+};
diff --git a/week08/Exercise4.cpp b/week08/Exercise4.cpp
new file mode 100644
index 0000000..28b3e2d
--- /dev/null
+++ b/week08/Exercise4.cpp
@@ -0,0 +1,141 @@
+#include "Exercise4.h"
+
+void FloatArray::free() {
+ delete[] numbers;
+}
+
+void FloatArray::copyFrom(const FloatArray& other) {
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+ this->numbers = new float[allocated];
+ for (int i = 0; i < this->lastUnused; i++) {
+ this->numbers[i] = other.numbers[i];
+ }
+}
+
+void FloatArray::resize() {
+ allocated *= 2;
+ float* moreNumbers = new float[allocated];
+ for (int i = 0; i < lastUnused; i++) {
+ moreNumbers[i] = numbers[i];
+ }
+ delete[] numbers;
+ numbers = moreNumbers;
+}
+
+FloatArray::FloatArray() {
+ numbers = nullptr;
+ lastUnused = allocated = 0;
+}
+
+FloatArray::~FloatArray() {
+ free();
+}
+
+FloatArray::FloatArray(const FloatArray& other) {
+ copyFrom(other);
+}
+
+FloatArray& FloatArray::operator=(const FloatArray& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+FloatArray::FloatArray(FloatArray&& other) {
+ this->numbers = other.numbers;
+ other.numbers = nullptr;
+
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+}
+
+FloatArray& FloatArray::operator=(FloatArray&& other) {
+ if (this != &other) {
+ free();
+
+ this->numbers = other.numbers;
+ other.numbers = nullptr;
+
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+ }
+ return *this;
+}
+
+void FloatArray::Add(float number) {
+ if (allocated == lastUnused) {
+ resize();
+ }
+ numbers[lastUnused++] = number;
+}
+
+FloatArray& FloatArray::operator+=(const FloatArray& other) {
+ for (int i = 0; i < other.lastUnused; i++) {
+ this->Add(other.numbers[i]);
+ }
+ return *this;
+}
+
+FloatArray& FloatArray::operator+=(float number) {
+ for (int i = 0; i < lastUnused; i++) {
+ numbers[i] += number;
+ }
+ return *this;
+}
+
+float& FloatArray::operator[](int index) {
+ if (index < 0 || lastUnused <= index) {
+ throw "Invalid index!";
+ }
+ return numbers[index];
+}
+
+FloatArray operator+(const FloatArray& left, const FloatArray& right) {
+ FloatArray output;
+ (output += left) += right;
+ return output;
+}
+
+FloatArray operator+(const FloatArray& left, float right) {
+ FloatArray output = left; // Копиращ конструктор
+ output += right;
+ return output;
+}
+
+bool operator==(const FloatArray& left, const FloatArray& right) {
+ if (left.lastUnused != right.lastUnused) {
+ return false;
+ }
+ for (int i = 0; i < left.lastUnused; i++) {
+ if (left.numbers[i] != right.numbers[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool operator!=(const FloatArray& left, const FloatArray& right) {
+ return !(left == right);
+}
+
+std::ostream& operator<<(std::ostream& ostr, const FloatArray& right) {
+ for (int i = 0; i < right.lastUnused; i++) {
+ ostr << right.numbers[i] << " ";
+ }
+ return ostr;
+}
+
+std::istream& operator>>(std::istream& istr, FloatArray& right) {
+ int length;
+ istr >> length;
+ right.lastUnused = 0;
+ for (int i = 0; i < length; i++) {
+ float temp;
+ istr >> temp;
+ right.Add(temp);
+ }
+ return istr;
+}
diff --git a/week08/Exercise4.h b/week08/Exercise4.h
new file mode 100644
index 0000000..588589e
--- /dev/null
+++ b/week08/Exercise4.h
@@ -0,0 +1,37 @@
+#include <iostream>
+
+class FloatArray {
+ float *numbers;
+ int lastUnused;
+ int allocated;
+
+ void free();
+ void copyFrom(const FloatArray& other);
+
+ void resize();
+
+public:
+ FloatArray();
+ ~FloatArray();
+ FloatArray(const FloatArray& other);
+ FloatArray& operator=(const FloatArray& other);
+ FloatArray(FloatArray&& other);
+ FloatArray& operator=(FloatArray&& other);
+
+ void Add(float number);
+
+ // Тези оператори променят аргумента си, затова е по-добре да са член-функции
+ FloatArray& operator+=(const FloatArray& other);
+ FloatArray& operator+=(float number);
+ // По дефиниция не може operator=, operator(), operator[] и operator-> да бъдат имплементирани
+ // като приятелски функции
+ float& operator[](int index);
+
+ // Тези оператори не променят аргументите си, затова е по-добре да са приятелски
+ friend FloatArray operator+(const FloatArray& left, const FloatArray& right);
+ friend FloatArray operator+(const FloatArray& left, float right);
+ friend bool operator==(const FloatArray& left, const FloatArray& right);
+ friend bool operator!=(const FloatArray& left, const FloatArray& right);
+ friend std::ostream& operator<<(std::ostream& ostr, const FloatArray& right);
+ friend std::istream& operator>>(std::istream& ostr, FloatArray& right);
+};
diff --git a/week08/Exercise5.hpp b/week08/Exercise5.hpp
new file mode 100644
index 0000000..80c435e
--- /dev/null
+++ b/week08/Exercise5.hpp
@@ -0,0 +1,203 @@
+#include <iostream>
+
+template <class T>
+class DynamicArray {
+ T *values;
+ int lastUnused;
+ int allocated;
+
+ void free();
+ void copyFrom(const DynamicArray<T>& other);
+
+ void resize();
+
+public:
+ DynamicArray();
+ ~DynamicArray();
+ DynamicArray(const DynamicArray<T>& other);
+ DynamicArray<T>& operator=(const DynamicArray<T>& other);
+ DynamicArray(DynamicArray<T>&& other);
+ DynamicArray<T>& operator=(DynamicArray<T>&& other);
+
+ void Add(const T& newValue);
+
+ // Тези оператори променят аргумента си, затова е по-добре да са член-функции
+ DynamicArray<T>& operator+=(const DynamicArray<T>& other);
+ DynamicArray<T>& operator+=(const T& newValue);
+ // По дефиниция не може operator=, operator(), operator[] и operator-> да бъдат имплементирани
+ // като приятелски функции
+ T& operator[](int index);
+
+ // Тези оператори не променят аргументите си, затова е по-добре да са приятелски
+ template <class U>
+ friend DynamicArray<U> operator+(const DynamicArray<U>& left, const DynamicArray<U>& right);
+ template <class U>
+ friend DynamicArray<U> operator+(const DynamicArray<U>& left, const U& right);
+ template <class U>
+ friend bool operator==(const DynamicArray<U>& left, const DynamicArray<U>& right);
+ template <class U>
+ friend bool operator!=(const DynamicArray<U>& left, const DynamicArray<U>& right);
+ template <class U>
+ friend std::ostream& operator<<(std::ostream& ostr, const DynamicArray<U>& right);
+ template <class U>
+ friend std::istream& operator>>(std::istream& ostr, DynamicArray<U>& right);
+};
+
+template <class T>
+void DynamicArray<T>::free() {
+ delete[] values;
+}
+
+template <class T>
+void DynamicArray<T>::copyFrom(const DynamicArray<T>& other) {
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+ this->values = new T[allocated];
+ for (int i = 0; i < this->lastUnused; i++) {
+ this->values[i] = other.values[i];
+ }
+}
+
+template <class T>
+void DynamicArray<T>::resize() {
+ allocated *= 2;
+ T* moreValues = new T[allocated];
+ for (int i = 0; i < lastUnused; i++) {
+ moreValues[i] = values[i];
+ }
+ delete[] values;
+ values = moreValues;
+}
+
+template <class T>
+DynamicArray<T>::DynamicArray() {
+ values = nullptr;
+ lastUnused = allocated = 0;
+}
+
+template <class T>
+DynamicArray<T>::~DynamicArray() {
+ free();
+}
+
+template <class T>
+DynamicArray<T>::DynamicArray(const DynamicArray<T>& other) {
+ copyFrom(other);
+}
+
+template <class T>
+DynamicArray<T>& DynamicArray<T>::operator=(const DynamicArray<T>& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+template <class T>
+DynamicArray<T>::DynamicArray(DynamicArray<T>&& other) {
+ this->values = other.values;
+ other.values = nullptr;
+
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+}
+
+template <class T>
+DynamicArray<T>& DynamicArray<T>::operator=(DynamicArray<T>&& other) {
+ if (this != &other) {
+ free();
+
+ this->values = other.values;
+ other.values = nullptr;
+
+ this->lastUnused = other.lastUnused;
+ this->allocated = other.allocated;
+ }
+ return *this;
+}
+
+template <class T>
+void DynamicArray<T>::Add(const T& number) {
+ if (allocated == lastUnused) {
+ resize();
+ }
+ values[lastUnused++] = number;
+}
+
+template <class T>
+DynamicArray<T>& DynamicArray<T>::operator+=(const DynamicArray<T>& other) {
+ for (int i = 0; i < other.lastUnused; i++) {
+ this->Add(other.values[i]);
+ }
+ return *this;
+}
+
+template <class T>
+DynamicArray<T>& DynamicArray<T>::operator+=(const T& number) {
+ for (int i = 0; i < lastUnused; i++) {
+ values[i] += number;
+ }
+ return *this;
+}
+
+template <class T>
+T& DynamicArray<T>::operator[](int index) {
+ if (index < 0 || lastUnused <= index) {
+ throw "Invalid index!";
+ }
+ return values[index];
+}
+
+template <class T>
+DynamicArray<T> operator+(const DynamicArray<T>& left, const DynamicArray<T>& right) {
+ DynamicArray<T> output;
+ (output += left) += right;
+ return output;
+}
+
+template <class T>
+DynamicArray<T> operator+(const DynamicArray<T>& left, T right) {
+ DynamicArray<T> output = left; // Копиращ конструктор
+ output += right;
+ return output;
+}
+
+template <class T>
+bool operator==(const DynamicArray<T>& left, const DynamicArray<T>& right) {
+ if (left.lastUnused != right.lastUnused) {
+ return false;
+ }
+ for (int i = 0; i < left.lastUnused; i++) {
+ if (left.values[i] != right.values[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <class T>
+bool operator!=(const DynamicArray<T>& left, const DynamicArray<T>& right) {
+ return !(left == right);
+}
+
+template <class T>
+std::ostream& operator<<(std::ostream& ostr, const DynamicArray<T>& right) {
+ for (int i = 0; i < right.lastUnused; i++) {
+ ostr << right.values[i] << " ";
+ }
+ return ostr;
+}
+
+template <class T>
+std::istream& operator>>(std::istream& istr, DynamicArray<T>& right) {
+ int length;
+ istr >> length;
+ right.lastUnused = 0;
+ for (int i = 0; i < length; i++) {
+ T temp;
+ istr >> temp;
+ right.Add(temp);
+ }
+ return istr;
+}
diff --git a/week08/Exercise6.cpp b/week08/Exercise6.cpp
new file mode 100644
index 0000000..22594a0
--- /dev/null
+++ b/week08/Exercise6.cpp
@@ -0,0 +1,27 @@
+#include "Exercise6.h"
+#include <iostream>
+
+NumberInput::NumberInput(int min, int max) {
+ std::cout << "Enter number [" << min << ", " << max << "]: ";
+ std::cin >> value;
+ if (value < min || max < value) {
+ throw "Number outside of range!";
+ }
+}
+
+int NumberInput::GetValue() {
+ return value;
+}
+
+int main() {
+ while(true) {
+ try {
+ NumberInput a(5, 10);
+ std::cout << a.GetValue() * 2 << std::endl;
+ break;
+ }
+ catch (const char* error) {
+ std::cout << error << std::endl;
+ }
+ }
+}
diff --git a/week08/Exercise6.h b/week08/Exercise6.h
new file mode 100644
index 0000000..3a24d6d
--- /dev/null
+++ b/week08/Exercise6.h
@@ -0,0 +1,7 @@
+class NumberInput {
+ int value;
+
+public:
+ NumberInput(int min, int max);
+ int GetValue();
+};
diff --git a/week08/Exercise7.cpp b/week08/Exercise7.cpp
new file mode 100644
index 0000000..60640b0
--- /dev/null
+++ b/week08/Exercise7.cpp
@@ -0,0 +1,97 @@
+#include "Exercise7.h"
+#include <cstring>
+
+void UserError::free() {
+ delete[] className;
+ delete[] propertyName;
+}
+
+void UserError::copyFrom(const UserError& other) {
+ this->className = new char[strlen(other.className) + 1];
+ strcpy(this->className, other.className);
+ this->propertyName = new char[strlen(other.propertyName) + 1];
+ strcpy(this->propertyName, other.propertyName);
+}
+
+UserError::UserError() {
+ className = propertyName = nullptr;
+ createdCount++;
+}
+
+UserError::~UserError() {
+ free();
+}
+
+UserError::UserError(const UserError& other) {
+ copyFrom(other);
+ createdCount++;
+}
+
+UserError& UserError::operator=(const UserError& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+UserError::UserError(UserError&& other) {
+ this->className = other.className;
+ other.className = nullptr;
+ this->propertyName = other.propertyName;
+ other.propertyName = nullptr;
+}
+
+UserError& UserError::operator=(UserError&& other) {
+ if (this != &other) {
+ free();
+
+ this->className = other.className;
+ other.className = nullptr;
+ this->propertyName = other.propertyName;
+ other.propertyName = nullptr;
+ }
+ return *this;
+}
+
+UserError::UserError(const char* className, const char* propertyName) {
+ this->className = new char[strlen(className) + 1];
+ strcpy(this->className, className);
+ this->propertyName = new char[strlen(propertyName) + 1];
+ strcpy(this->propertyName, propertyName);
+ createdCount++;
+}
+
+std::ostream& operator<<(std::ostream& ostr, const UserError& right) {
+ return ostr << "Invalid user info in class " << right.className << " at " << right.propertyName << "!" << std::endl;
+}
+
+int UserError::GetCreatedCount() {
+ return createdCount;
+}
+
+NumberInput::NumberInput(int min, int max) {
+ std::cout << "Enter number [" << min << ", " << max << "]: ";
+ std::cin >> value;
+ if (value < min || max < value) {
+ throw UserError("NumberInput", "constructor");
+ }
+}
+
+int NumberInput::GetValue() {
+ return value;
+}
+
+int main() {
+ while(true) {
+ try {
+ NumberInput a(5, 10);
+ std::cout << a.GetValue() * 2 << std::endl;
+ break;
+ }
+ catch (const UserError& error) {
+ std::cout << error;
+ }
+ }
+ std::cout << UserError::GetCreatedCount() << std::endl;
+}
diff --git a/week08/Exercise7.h b/week08/Exercise7.h
new file mode 100644
index 0000000..05d63c7
--- /dev/null
+++ b/week08/Exercise7.h
@@ -0,0 +1,33 @@
+#include <iostream>
+
+class UserError {
+ char* className;
+ char* propertyName;
+
+ void free();
+ void copyFrom(const UserError& other);
+
+ inline static int createdCount = 0;
+
+public:
+ UserError();
+ ~UserError();
+ UserError(const UserError& other);
+ UserError& operator=(const UserError& other);
+ UserError(UserError&& other);
+ UserError& operator=(UserError&& other);
+
+ UserError(const char* className, const char* propertyName);
+
+ friend std::ostream& operator<<(std::ostream& ostr, const UserError& right);
+
+ static int GetCreatedCount();
+};
+
+class NumberInput {
+ int value;
+
+public:
+ NumberInput(int min, int max);
+ int GetValue();
+};
diff --git a/week08/README.md b/week08/README.md
new file mode 100644
index 0000000..31cbdc2
--- /dev/null
+++ b/week08/README.md
@@ -0,0 +1,153 @@
+# Задачи - ООП, Седмица 8, 11.04.2024
+
+*Този файл е копие на задачите от: [syndamia.com/teaching/oop-2023/week8](https://syndamia.com/teaching/oop-2023/week8)*
+
+## Преговорни
+
+### Задача 1 - Голяма петица
+
+Имплементирайте клас `StreetList`, който запазва имената на улици (низове с произволна дължина) в динамичен масив.
+Може да се добавят нови имена в края на списъка, като съответния (вътрешен) масив трябва да се уголеми.
+
+Имплементирайте голяма петица за класа.
+
+### Задача 2 - Файлове и класове
+
+Имплементирайте клас `Person`, който запазва трите имена (низове с произволна дължина) и идентификационния номер (цяло неотрицателно число) на човек.
+Имплементирайте голяма петица.
+
+Имплементирайте методи `SaveText` и `LoadText`, които съответно записват и четат (тоест член-данните стават равни на тези от файла) данните си в/от **текстови** файл с подадено име.
+Аналогично имплементирайте `SaveBinary` и `LoadBinary`, които работят с **двоични** файлове.
+
+## Лесни
+
+### Задача 3
+
+Имплементирайте шаблонната структура `Pair`, която приема два типа и запазва по една стойност от всеки тип.
+
+### Задача 4
+
+Имплементирайте клас `FloatArray`, който съдържа списък с числа с плаваща запетая.
+Може да добавяте нови числа в края на този списък.
+Имплементирйате голяма петица.
+
+Имплементирайте оператори:
+
+- += и +, които конкатенират два FloatArray-я. += вмъква елементите от десния масив в края на левия, + връща нов масив в който първо са елементите от левия масив и след тях са тези от десния.
+- += и +, които приемат FloatArray и число (с плаваща запетая) и го прибавят към всеки елемент на FloatArray-я
+- [], които връщат референция към елементът на подадения индекс. При невалиден хвърлят грешка.
+- == и !=, които сравняват два FloatArray-я покомпонентно.
+ Ако се различават по брой елементи или ако имат две различни стойности на еднакъв индекс, тогава не са равни.
+- <<, който вмъква всички стойности в подадения поток, разделени с шпация
+- >>, който презаписва всички стойности, разделени с шпация, четейки от подадени поток
+
+### Задача 5
+
+Имплементирайте класът и неговите оператори от предходната задача като темплейтен (шаблонен) клас с име `DynamicArray`.
+Очевидно шаблонния тип определя типа на списъка с елементи.
+
+### Задача 6
+
+Имплементирайте клас `NumberInput`, който запазва целочислена стойност.
+В конструктора се подава минимална и максимална възможна стойност, след това (все още в конструктора) се изкарва на екрана съответно съобщение и се приема потребителски вход.
+Ако той не е валиден или е извън подадения обхват, трябва да хвърлите грешка.
+
+В main създайте обект от този клас.
+Ако се хвърли грешка, прихванете я, изкарайте на екрана съответното съобщение и пробвайте пак.
+Това се повтаря докато обекта не е успешно създаден, след което изкарвате въведената стойност по две.
+
+### Задача 7
+
+Имплементирайте клас `UserError`, чиято употреба е да се хвърля като грешка.
+За тази цел нека да запазва два низа, които се приемат в конструктора: името на клас и името на член-данната.
+
+Имплементирайте голяма петица и оператор<<, който изкарва съобщение с информация за класа и член-данната в подадения поток.
+Следете бройката на създадени `UserError` инстанции в самия клас (статична променлива) и имплементирате нужната (статична) член-функция, която връща този брой.
+
+Преобразувайте последната задача, така че да хвърля грешка от този клас.
+В края на програмата изкарайте колко грешки са се хвърлили **използвайки статичните членове на UserError**.
+
+## Трудни задачи
+
+### Задача 8
+
+Имплементирайте шаблонен клас `UserInput`, който запазва стойност от подадения тип.
+Ако типа е указател, тогава заделяте динамична памет за един такъв елемент.
+За проверка на типа използвайте [partial template specialization](https://en.cppreference.com/w/cpp/language/partial_specialization).
+
+В шаблона (`template <...>`) се приема указател към валидираща функция, която приема стойността от съответния тип и връща булева стойност.
+В конструктора се приема от входа нужната стойност и ако стойността е неуспешно приета или валидиращата функция върне false, тогава хвърляте грешка.
+Ако типа е указател, не забравяйте да освободите паметта.
+
+В класа следете статично за броя пъти когато е хвърлена грешка.
+
+### Задача 9
+
+&:important В тази задача се изикват помощни класове, прочетете цялото условие преди имплементиране!
+
+Имплементирайте шаблонен клас `Dictionary`, който запазва два динамично-заделени масива: първия е със стойност от подадения тип, втория е с низове.
+Низовете ще се използват за индексиране, вместо числа.
+Разбира се, очаквайте да може да се уразмерява.
+Имплементирайте голяма петица.
+
+Имплементирайте оператор:
+
+- <<=, който вмъква всички стойности от десния `Dictionary` в левия
+- [], който приема низ и връща референция "към" стойността.
+ Ако няма записана стойност на съответния индекс, тогава връщате референция в която може да се запише стойност.
+- [], който приема число, което се конвертира до низ и работи както предходния оператор
+- [], който приема низове (или числа), разделени със запетая и връща "масив" само с тези стойности
+- delete, който приема стойност, върната от оператор[] и "премахва" съответната стойност от `Dictionary`
+- префиксен++, префиксен+ и префиксен-, които ще се използват за итериране.
+ - ++ връща инкрементира индекса на сегашната стойност.
+ Ако индекса е равен на броя запазени стойности, тогава става нула.
+ По подразбиране индекса е броя.
+ Връща true ако след инкрементиране индекса не е броя.
+ - + връща референция към стойността на сегашния индекс
+ - - връща сегашния (низов) индекс
+- ->, такъв че можем да правим `a->(&func1)->(&func2)` и `a->[&func3]->[&func4]`.
+ Върху всяка двойка индекс-стойност се прилагат &func1 и &func2 (приемат индекс и стойност като параметри), които връщат нова стойност, заместваща сегашната.
+ &func3, &func4 аналогично приемат индекс и стойност, но връщат нов индекс.
+
+В края на задачата трябва да можете да правите:
+
+```cpp
+int doubleUp(const char* index, int value) {
+ return value * 2;
+}
+int sumIndexValue(const char* index, int value) {
+ return atoi(index) + value;
+}
+const char* indToName(const char* index, int value) {
+ if (strcmp(index, "2")) {
+ return "two";
+ }
+ return index;
+}
+
+int main() {
+ Dictionary<int> a;
+ a["first"] = 8;
+ a[2] = 13;
+ a[89] = -68;
+
+ Dictionary<int> b;
+ b["wow"] = 99;
+ b["nth"] = 773;
+
+ a <<= b;
+
+ /* някакъв тип */ two = a["first", 2];
+
+ delete a["wow"];
+
+ a->(&doubleUp)->(&sumIndexValue)->[&indToName];
+
+ while (++a) {
+ std::cout << +a << " at " << -a << ",";
+ /* Ще изкара на конзолата:
+ * 16 at first,52 at two,-12104 at 89,1546 at nth,
+ */
+ }
+}
+```