diff options
| -rw-r--r-- | week08/Exercise1.cpp | 80 | ||||
| -rw-r--r-- | week08/Exercise1.h | 20 | ||||
| -rw-r--r-- | week08/Exercise2.cpp | 160 | ||||
| -rw-r--r-- | week08/Exercise2.h | 22 | ||||
| -rw-r--r-- | week08/Exercise3.hpp | 5 | ||||
| -rw-r--r-- | week08/Exercise4.cpp | 141 | ||||
| -rw-r--r-- | week08/Exercise4.h | 37 | ||||
| -rw-r--r-- | week08/Exercise5.hpp | 203 | ||||
| -rw-r--r-- | week08/Exercise6.cpp | 27 | ||||
| -rw-r--r-- | week08/Exercise6.h | 7 | ||||
| -rw-r--r-- | week08/Exercise7.cpp | 97 | ||||
| -rw-r--r-- | week08/Exercise7.h | 33 | ||||
| -rw-r--r-- | week08/README.md | 153 |
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*)¤tLength, sizeof(currentLength)); + firstName = new char[currentLength + 1]; + inFile.read(firstName, sizeof(char) * currentLength); + firstName[currentLength] = '\0'; + + inFile.read((char*)¤tLength, sizeof(currentLength)); + middleName = new char[currentLength + 1]; + inFile.read(middleName, sizeof(char) * currentLength); + middleName[currentLength] = '\0'; + + inFile.read((char*)¤tLength, 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, + */ + } +} +``` |
