diff options
feat(Week09): Add solutions
5 files changed, 414 insertions, 0 deletions
| -rw-r--r-- | Week09/Exercise05/String.cpp | 75 | ||||
| -rw-r--r-- | Week09/Exercise05/String.h | 28 | ||||
| -rw-r--r-- | Week09/Exercise05/StringArray.cpp | 219 | ||||
| -rw-r--r-- | Week09/Exercise05/StringArray.h | 80 | ||||
| -rw-r--r-- | Week09/Exercise05/main.cpp | 12 |
diff --git a/Week09/Exercise05/String.cpp b/Week09/Exercise05/String.cpp new file mode 100644 index 0000000..903aa60 --- /dev/null +++ b/Week09/Exercise05/String.cpp @@ -0,0 +1,75 @@ +#include "String.h" +#include <cstring> +#include <iostream> + +void String::free() { + delete[] str; +} + +void String::copyFrom(const String& other) { + length = other.length; + // Не забравяме за терминиращата нула + str = new char[length + 1]; + strcpy(str, other.str); +} + +String::String() { + str = nullptr; + length = 0; +} + +String::~String() { + free(); +} + +String::String(const String& other) { + copyFrom(other); +} + +String& String::operator=(const String& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +String::String(String&& other) { + str = other.str; + length = other.length; + + other.str = nullptr; + other.length = 0; +} + +String& String::operator=(String&& other) { + if (this != &other) { + free(); + + str = other.str; + length = other.length; + + other.str = nullptr; + other.length = 0; + } + return *this; +} + +String::String(unsigned length) { + this->length = length; + this->str = new char[length + 1]; + this->str[length] = '\0'; +} + +void String::Copy(const char* str) { + if (this->str == nullptr) { + length = strlen(str); + this->str = new char[length + 1]; + } + strncpy(this->str, str, length); + this->str[length] = '\0'; +} + +const char* String::GetStr() const { + return str; +} diff --git a/Week09/Exercise05/String.h b/Week09/Exercise05/String.h new file mode 100644 index 0000000..08c7a79 --- /dev/null +++ b/Week09/Exercise05/String.h @@ -0,0 +1,28 @@ +#ifndef _STRING +#define _STRING + +#include <ostream> + +class String { + char* str; + unsigned length; + + void free(); + void copyFrom(const String& other); + +public: + String(); + ~String(); + String(const String& other); + String& operator=(const String& other); + + String(String&& other); + String& operator=(String&& other); + + String(unsigned length); + void Copy(const char* other); + + const char* GetStr() const; +}; + +#endif /* _STRING */ diff --git a/Week09/Exercise05/StringArray.cpp b/Week09/Exercise05/StringArray.cpp new file mode 100644 index 0000000..c3eca35 --- /dev/null +++ b/Week09/Exercise05/StringArray.cpp @@ -0,0 +1,219 @@ +#include "StringArray.h" +#include <iostream> + +void StringArray::free() { + delete[] strings; +} + +void StringArray::copyFrom(const StringArray& other) { + stringsCount = other.stringsCount; + stringsAlloc = other.stringsAlloc; + stringsAssigned = other.stringsAssigned; + + strings = new String[stringsAlloc]; + for (unsigned i = 0; i < stringsCount; ++i) + strings[i] = other.strings[i]; +} + +void StringArray::resize() { + stringsAlloc = stringsAlloc == 0 ? 8 : stringsAlloc * 2; + String* stringsLarger = new String[stringsAlloc]; + + for (unsigned i = 0; i < stringsCount; ++i) + stringsLarger[i] = strings[i]; + + delete[] strings; + strings = stringsLarger; +} + +StringArray::StringArray() { + strings = nullptr; + stringsCount = stringsAlloc = stringsAssigned = 0; +} + +StringArray::~StringArray() { + free(); +} + +StringArray::StringArray(const StringArray& other) { + copyFrom(other); +} + +StringArray& StringArray::operator=(const StringArray& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +StringArray::StringArray(StringArray&& other) { + strings = other.strings; + stringsCount = other.stringsCount; + stringsAlloc = other.stringsAlloc; + stringsAssigned = other.stringsAssigned; + + other.strings = nullptr; + other.stringsCount = other.stringsAlloc = other.stringsAssigned = 0; +} + +StringArray& StringArray::operator=(StringArray&& other) { + if (this != &other) { + free(); + + strings = other.strings; + stringsCount = other.stringsCount; + stringsAlloc = other.stringsAlloc; + stringsAssigned = other.stringsAssigned; + + other.strings = nullptr; + other.stringsCount = other.stringsAlloc = other.stringsAssigned = 0; + } + return *this; +} + +void StringArray::PushLength(unsigned length) { + if (stringsCount >= stringsAlloc) + resize(); + strings[stringsCount++] = String(length); +} + +void StringArray::PushString(const char* str) { + if (stringsAssigned >= stringsAlloc) + resize(); + strings[stringsAssigned++].Copy(str); + + if (stringsAssigned > stringsCount) + stringsCount = stringsAssigned; +} + +StringArray& StringArray::operator[](const Z& expectedNumbers) { + for (unsigned i = 0; i < expectedNumbers.numbersCount; ++i) { + PushLength(expectedNumbers.numbers[i]); + } + return *this; +} + +StringArray& StringArray::operator()(const StringArray& strings) { + for (unsigned i = 0; i < strings.stringsAssigned; ++i) { + PushString(strings.strings[i].GetStr()); + } + return *this; +} + +StringArray& StringArray::operator()(const char* str) { + PushString(str); + return *this; +} + +StringArray::StringArray(const char* str) : StringArray() { + PushString(str); +} + +StringArray& StringArray::operator|(const char* str) { + PushString(str); + return *this; +} + +// Това не е нужно по условие, но ще ни е +// полезно за тестване. +std::ostream& operator<<(std::ostream& ostr, const StringArray& sa) { + for (unsigned i = 0; i < sa.stringsAssigned; ++i) + ostr << sa.strings[i].GetStr() << std::endl; + return ostr; +} + +/* Помощен клас Z */ + +void Z::free() { + delete[] numbers; +} + +void Z::copyFrom(const Z& other) { + numbersCount = other.numbersCount; + numbersAlloc = other.numbersAlloc; + + numbers = new unsigned[numbersAlloc]; + for (unsigned i = 0; i < numbersCount; ++i) + numbers[i] = other.numbers[i]; +} + +void Z::resize() { + numbersAlloc = numbersAlloc == 0 ? 8 : numbersAlloc * 2; + unsigned* numbersLarger = new unsigned[numbersAlloc]; + + for (unsigned i = 0; i < numbersCount; ++i) + numbersLarger[i] = numbers[i]; + + delete[] numbers; + numbers = numbersLarger; +} + +Z::Z() { + numbers = nullptr; + numbersCount = numbersAlloc = 0; +} + +Z::~Z() { + free(); +} + +Z::Z(const Z& other) { + copyFrom(other); +} + +Z& Z::operator=(const Z& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +Z::Z(Z&& other) { + numbers = other.numbers; + numbersAlloc = other.numbersAlloc; + numbersCount = other.numbersCount; + + other.numbers = nullptr; + other.numbersCount = other.numbersAlloc = 0; +} + +Z& Z::operator=(Z&& other) { + if (this != &other) { + free(); + + numbers = other.numbers; + numbersAlloc = other.numbersAlloc; + numbersCount = other.numbersCount; + + other.numbers = nullptr; + other.numbersCount = other.numbersAlloc = 0; + } + return *this; +} + +Z::Z(unsigned number) { + numbersAlloc = 8; + numbersCount = 1; + numbers = new unsigned[numbersAlloc]; + numbers[0] = number; +} + +// Това е един метод да имплементираме operator++ и operator+, +// където с ++ все едно подсказваме че ще добавяме елемент и с +// + се добавя елемента. +// Валидно е и ++ да не върши нищо и цялата логика да е в +. +// Но така задължаваме употребата на "+++". + +Z& Z::operator++(int) { + if (numbersCount + 1 >= numbersAlloc) + resize(); + return *this; +} + +Z& Z::operator+(const Z& rhs) { + for (unsigned i = 0; i < rhs.numbersCount && numbersCount < numbersAlloc; ++i) + numbers[numbersCount++] = rhs.numbers[i]; + return *this; +} diff --git a/Week09/Exercise05/StringArray.h b/Week09/Exercise05/StringArray.h new file mode 100644 index 0000000..4b15ba0 --- /dev/null +++ b/Week09/Exercise05/StringArray.h @@ -0,0 +1,80 @@ +#ifndef _STRINGARRAY +#define _STRINGARRAY + +#include "String.h" +#include <ostream> + +// Декларация на класа, за да може в StringArray +// да си го използваме преди пълната дефиниция +class Z; + +class StringArray { + String* strings; + unsigned stringsCount; + unsigned stringsAlloc; + + unsigned stringsAssigned; + + void free(); + void copyFrom(const StringArray& other); + void resize(); + +public: + StringArray(); + ~StringArray(); + StringArray(const StringArray& other); + StringArray& operator=(const StringArray& other); + + StringArray(StringArray&& other); + StringArray& operator=(StringArray&& other); + + void PushLength(unsigned length); + void PushString(const char* str); + + StringArray& operator[](const Z& expectedNumbers); + + // Можем да създадем помощен клас "PassedStrings". + // Обаче нямаме ограничение което задължава StringArray и + // PassedStrings да са различни класове. + // Можем и просто да се възползваме от StringArray, + // и да си спестим писане на код. + StringArray& operator()(const StringArray& strings); + StringArray& operator()(const char* str); + StringArray(const char* str); + + // Оператор "|" е ляво асоциативен + StringArray& operator|(const char* str); + + // Това не е нужно по условие, но ще ни е + // полезно за тестване. + friend std::ostream& operator<<(std::ostream& ostr, const StringArray& sa); +}; + +class Z { + unsigned* numbers; + unsigned numbersCount; + unsigned numbersAlloc; + + void free(); + void copyFrom(const Z& other); + void resize(); + +public: + Z(); + ~Z(); + Z(const Z& other); + Z& operator=(const Z& other); + + Z(Z&& other); + Z& operator=(Z&& other); + + Z(unsigned num); + + Z& operator++(int); + Z& operator+(const Z& rhs); + + friend StringArray; +}; + + +#endif /* _STRINGARRAY */ diff --git a/Week09/Exercise05/main.cpp b/Week09/Exercise05/main.cpp new file mode 100644 index 0000000..8bf6a6c --- /dev/null +++ b/Week09/Exercise05/main.cpp @@ -0,0 +1,12 @@ +#include "StringArray.h" +#include <iostream> + +int main() { + StringArray s; + + // Защо за числата трябва да конвертираме всички, а при | конвертираме само първия? + s[ Z(7) +++ Z(4) +++ Z(3) ] ("") (StringArray("Hello")|"World") [ Z(4) +++ Z(5) +++ Z(1) ] ("!") [ Z(2) ] (StringArray("Code")|"A"|"B"); + + std::cout << s; + return 0; +} |
