seminar2
This commit is contained in:
		
							parent
							
								
									46d1c64684
								
							
						
					
					
						commit
						ab6732eded
					
				
					 98 changed files with 10319 additions and 0 deletions
				
			
		|  | @ -0,0 +1,45 @@ | |||
| /*
 | ||||
|     Создадим свою строку | ||||
| 
 | ||||
|     Один из самых главных недостатков языка C это работа со строками. | ||||
|     Строки в языке C это просто массивы элементов типа char | ||||
|         char str[100];    или   char* p = malloc(100); | ||||
| 
 | ||||
|     В языке C работать со строками очень неудобно по многим причинам: | ||||
|         - Нужно постоянно следить за тем, чтобы строка умещалась в памяти, которая под нею выделена. | ||||
|         - Строку можно выделить на Стеке, используя обычный массив, и тогда её вместимость нельзя будет увеличить, | ||||
|             а можно выделить в Куче, но тогда придётся самостоятельно выделять и освобождать память | ||||
|             и следить, чтобы не произошли утечки памяти. | ||||
|         - Строки нельзя просто копировать, сравнивать, складывать и т. д. Для этого нужно использовать | ||||
|             специальные функции типа strcpy и другие функции из библиотеки <string.h>. | ||||
| 
 | ||||
| 
 | ||||
|     Создадим же удобный класс строки | ||||
|     Такой чтобы можно было удобно создавать строки, приравнивать, складывать и сравнивать. | ||||
|     Не заботясь о выделении/удалении памяти, и о том, что строка помещается в выделенную память. | ||||
| 
 | ||||
|     Чтобы можно было писать вот такой код: | ||||
|      | ||||
|         String a = "Cat"; | ||||
|         String b = "Dog"; | ||||
|         cout << a << " " << b << endl; | ||||
| 
 | ||||
|         String c = "Mouse"; | ||||
|         c = a + b; | ||||
|         c += "Bear"; | ||||
|          | ||||
|         if (c == "CatDogBear") | ||||
|             cout << "Yes" << endl; | ||||
|          | ||||
|         c = a; | ||||
|         cout << c << endl; | ||||
| 
 | ||||
| 
 | ||||
|     (String в переводе с английского это Строка) | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int main() {} | ||||
| 
 | ||||
|  | @ -0,0 +1,165 @@ | |||
| /*
 | ||||
| 
 | ||||
|     Создадим строку, которая при создании (т.е в конструкторе) будет автоматически выделять необходимую память в Куче. | ||||
|     В чём-то реализация этой строки будет похожа на реализацию динамического массива из прошлого семестра. | ||||
| 
 | ||||
|     У класса строки 3 поля: | ||||
| 
 | ||||
|         mSize       -  размер - количество символов в строке (без учёта \0) | ||||
|         mCapacity   -  вместимость - количество выделенной памяти в Куче | ||||
|         mpData      -  указатель на выделенную память в Куче. В этой памяти строка будет иметь такой же вид, как и строка языка C.  | ||||
|                        В частности она будет иметь символ '\0' на конце.  | ||||
|                        Символ '\0' на конце оставим, чтобы было удобно конвертировать нашу строку в строку в стиле C. | ||||
| 
 | ||||
|      | ||||
|     Размер и вместимость это разные величины.  | ||||
| 
 | ||||
|         Например, для хранения строки "Cat" может быть выделено памяти под 10 символов, хоть и под эту строку было бы достаточно всего 4. | ||||
|         Представьте, что у вас есть длинная строка и вы хотите удалить последний символ в ней. | ||||
|         Если бы мы не хранили вместимость, а всегда выделяли памяти в притык, то в этом простом случае нам бы пришлось | ||||
|         перевыделять память и копировать всю строку в новую память. | ||||
|         Если же мы храним вместимость, то достаточно всего лишь уменьшить размер на 1 и поставит \0 в новый конец строки. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     Теперь создадим конструктор, который будет выделять память и заполнять его нужным образом | ||||
|          | ||||
|         Конструктор   String(const char* str)   конструирует нашу строку из строки в стиле C. | ||||
|         Принимаем на вход именно константную строку, так как в этом случае в конструктор можно будет | ||||
|         передать как константные, так и неконстантые строки. | ||||
|         Если бы мы написали так   String(char* str)   , то в конструктор нельзя было бы передать константные строки. | ||||
| 
 | ||||
| 
 | ||||
|         В строках: | ||||
| 
 | ||||
|             size_t i = 0; | ||||
|             while (str[i] != '\0') | ||||
|                 i++; | ||||
|             mSize = i; | ||||
|             mCapacity = i + 1; | ||||
| 
 | ||||
|         мы находим размер переданной строки (strlen не используем, чтобы не связываться со старой библиотекой) | ||||
|         Вместимость на 1 больше, так как нужно учесть память под символ /0 | ||||
| 
 | ||||
| 
 | ||||
|         В строке: | ||||
| 
 | ||||
|             mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         выделяем необходимую память | ||||
| 
 | ||||
| 
 | ||||
|         В строках: | ||||
| 
 | ||||
|             for (size_t i = 0; str[i] != '\0'; i++) | ||||
|                 mpData[i] = str[i]; | ||||
|             mpData[mSize] = '\0'; | ||||
|      | ||||
|         копируем содержимое переданной строки в только что выделенную память. | ||||
| 
 | ||||
| 
 | ||||
|     Другие методы класса String: | ||||
| 
 | ||||
|         getSize     - возвращает размер строки | ||||
|         getCapacity - возвращает вместимость строки | ||||
|         cStr        - возвращает строку в стиле C, то есть указатель на массив из char-ов с конечным символом \0 | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i] != '\0'; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize() const  | ||||
|     { | ||||
|         return mSize; | ||||
|     } | ||||
| 
 | ||||
|     size_t getCapacity() const  | ||||
|     { | ||||
|         return mCapacity; | ||||
|     } | ||||
| 
 | ||||
|     const char* cStr() const  | ||||
|     { | ||||
|         return mpData; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& out, const String& s)  | ||||
| { | ||||
|     out << s.cStr(); | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Dog"; | ||||
|     String c = "Lion";    | ||||
| 
 | ||||
|     cout << a << endl << b << endl << c << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*  
 | ||||
|     Задание: | ||||
| 
 | ||||
|     1) Создайте конструктор String(), который будет создавать пустую строку | ||||
|             (mSize = 0, mCapacity = 1,      строка mpData содержит в себе 1 символ ('\0')) | ||||
| 
 | ||||
|         Конструктор, который не принимает аргументов называется конструктором по умолчанию | ||||
| 
 | ||||
| 
 | ||||
|     2) Создайте конструктор String(size_t n, char a), который будет создавать строку из n символов a | ||||
|             (mSize = n, mCapacity = n + 1,  строка mpData содержит в себе n + 1 символ (n раз a и '\0')) | ||||
| 
 | ||||
| 
 | ||||
|     2) Создайте конструктор String(const String& s), который будет создавать строку String из другой строки String | ||||
|             (mSize = s.mSize, mCapacity = s.mCapacity,  строка mpData содержит в себе копию строки s.mpData) | ||||
| 
 | ||||
|         Конструктор, который создаёт объект по другому объекту такого же типа называется конструктором копирования. | ||||
| 
 | ||||
| 
 | ||||
|     Протестируйте эти конструкторы: | ||||
|         String a; | ||||
|         cout << a << endl; | ||||
| 
 | ||||
|         String b(10, 'q'); | ||||
|         cout << b << endl; | ||||
| 
 | ||||
|         String c("Cat"); | ||||
|         cout << c << endl; | ||||
| 
 | ||||
|         String d(c); | ||||
|         cout << d << endl; | ||||
| */ | ||||
|  | @ -0,0 +1,104 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "Construtor from const char*" << endl; | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i] != '\0'; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "Default Construtor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(size_t n, char a) | ||||
|     { | ||||
|         cout << "Construtor n equal characters" << endl; | ||||
|         mSize = n; | ||||
|         mCapacity = n + 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = a; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String(const String& s) | ||||
|     { | ||||
|         cout << "Copy Constructor" << endl; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = s.mCapacity; | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize() const  | ||||
|     { | ||||
|         return mSize; | ||||
|     } | ||||
| 
 | ||||
|     size_t getCapacity() const  | ||||
|     { | ||||
|         return mCapacity; | ||||
|     } | ||||
| 
 | ||||
|     const char* cStr() const  | ||||
|     { | ||||
|         return mpData; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a; | ||||
|     cout << a << endl << endl; | ||||
| 
 | ||||
|     String b(10, 'q'); | ||||
|     cout << b << endl << endl; | ||||
|      | ||||
| 
 | ||||
|     String c = "Cat"; | ||||
|     cout << c << endl << endl; | ||||
| 
 | ||||
| 
 | ||||
|     String d(c); | ||||
|     cout << c << endl << endl; | ||||
| } | ||||
|  | @ -0,0 +1,109 @@ | |||
| /*
 | ||||
|     Делегирующий конструктор | ||||
| 
 | ||||
|     В разных конструкторах может быть повторяющийся код. | ||||
|     Повторений кода иногда можно избежать если писать один конструктор на основе уже написанного. | ||||
| 
 | ||||
|     Это можно сделать с помощью синтаксиса так называемого делегирующего конструктора | ||||
|     После объявления конструктора, но перед его телом можно написать двоеточие и вызвать другой конструктор | ||||
|      | ||||
|     Например: | ||||
| 
 | ||||
|         String() : String("") | ||||
|         { | ||||
|             cout << "Default Constructor" << endl; | ||||
|         } | ||||
| 
 | ||||
|     Этот конструктор сначала вызовет конструктор String(const char* str) с аргументом "" (то есть пустой строкой) | ||||
|     а потом исполнит тело данного коструктора (в данном случае напечатает Default Constructor). | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "Constructor" << endl; | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i] != '\0'; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") | ||||
|     { | ||||
|         cout << "Default Constructor" << endl; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String(const String& s) : String(s.cStr()) | ||||
|     { | ||||
|         cout << "Copy Constructor" << endl; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize() const  | ||||
|     { | ||||
|         return mSize; | ||||
|     } | ||||
| 
 | ||||
|     size_t getCapacity() const  | ||||
|     { | ||||
|         return mCapacity; | ||||
|     } | ||||
| 
 | ||||
|     const char* cStr() const  | ||||
|     { | ||||
|         return mpData; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a; | ||||
|     cout << "a = " << a << endl << endl; | ||||
| 
 | ||||
| 
 | ||||
|     String b = "Cat"; | ||||
|     cout << "b = " << b << endl << endl; | ||||
| 
 | ||||
| 
 | ||||
|     String c(b); | ||||
|     cout << "c = " << c << endl << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|     Задача: | ||||
| 
 | ||||
|         Попробуйте понять без запуска, что напечатает данная программа | ||||
| */ | ||||
|  | @ -0,0 +1,113 @@ | |||
| /*
 | ||||
|     В конструкторе мы выделили память с malloc, но нигде в программе её не освободили | ||||
|     Соответственно, в предыдущей программе у нас есть очень серьёзная ошибка - утечка памяти. | ||||
|      | ||||
|     Где же нужно освобождать память? | ||||
|     Если память была выделена в конструкторе при создании объекта, то выделять её нужно при удалении объекта. | ||||
|     Для того, чтобы испольнить ваш код при удалении объекта существует специальный метод, который называется Деструктор. | ||||
|      | ||||
| 
 | ||||
|     Деструктор - это специальный метод, который вызывается тогда, когда объект уничтожается | ||||
|     Объекты, созданные на стеке удаляются при выходе из области видимости | ||||
| 
 | ||||
| 
 | ||||
|     Синтаксис деструктора такой: | ||||
| 
 | ||||
|         ~String() | ||||
|         { | ||||
|             ... | ||||
|         } | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "Constructor of " << str << endl; | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i] != '\0'; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "Destructor of " << mpData << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize() const  | ||||
|     { | ||||
|         return mSize; | ||||
|     } | ||||
| 
 | ||||
|     size_t getCapacity() const  | ||||
|     { | ||||
|         return mCapacity; | ||||
|     } | ||||
| 
 | ||||
|     const char* cStr() const  | ||||
|     { | ||||
|         return mpData; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Dog"; | ||||
|        | ||||
|     if (true) | ||||
|     { | ||||
|         String c = "Lion";  | ||||
|     } | ||||
| 
 | ||||
|     String c = "Bear"; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* 
 | ||||
|     Задание: | ||||
|      | ||||
|         1)  Что напечатает данная программа? | ||||
|             В каком порядке вызовутся конструкторы | ||||
| 
 | ||||
|          | ||||
|         2)  Если создать строку String в цикле, то будут ли каждую итерацию вызываться конструкторы и деструкторы? | ||||
| 
 | ||||
|             for (int i = 0; i < 10; ++i) | ||||
|             { | ||||
|                 String s = "Elephant"; | ||||
|             } | ||||
| */ | ||||
|  | @ -0,0 +1,94 @@ | |||
| /*
 | ||||
|     Оператор сложения | ||||
| 
 | ||||
|     Оператор сложения для строк должен принимать 2 строки и возвращать новую строку, равную результату конкатенации двух строк | ||||
|     Если строка  a = "Cat"  , а строка  b = "Mouse"  , то их конкатенация это  a + b = "CatMouse" | ||||
| 
 | ||||
|     Оператор сложения должен принимать свои аргументы по константной ссылке | ||||
|         по ссылке, чтобы не копировать объект лишний раз при передаче в функцию | ||||
|         по константной, потому что мы не будем менять принимаемые объекты внутри функции | ||||
| 
 | ||||
| 
 | ||||
|     То есть прототип оператора сложения, если его делать с помощью обычной функции, должен выглядеть так: | ||||
| 
 | ||||
|         String operator+(const String& a, const String& b) | ||||
| 
 | ||||
| 
 | ||||
|     Прототип оператора сложения, если его делать с помощью метода класса String, должен выглядеть так: | ||||
| 
 | ||||
|         String operator+(const String& b) const | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "Constructor of " << str << endl; | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i] != '\0'; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "Destructor of " << mpData << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Mouse"; | ||||
|        | ||||
|     cout << a + b << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* 
 | ||||
|     Задание: | ||||
|      | ||||
|         1)  Написать оператор сложения для строки String в виде свободной функции | ||||
|             В этом случае эту функцию нужно сделать дружественной классу String, | ||||
|             чтобы она имела доступ к приватным полям класса | ||||
| 
 | ||||
|         2)  Написать оператор сложения для строки String в виде метода класса String | ||||
| */ | ||||
|  | @ -0,0 +1,86 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i] != '\0'; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| 
 | ||||
|     friend String operator+(const String& a, const String& b); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| String operator+(const String& a, const String& b) | ||||
| { | ||||
|     String result; | ||||
| 
 | ||||
|     result.mSize = a.mSize + b.mSize; | ||||
|     result.mCapacity = result.mSize + 1; | ||||
|     result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity); | ||||
| 
 | ||||
|     for (size_t i = 0; i < a.mSize; ++i) | ||||
|         result.mpData[i] = a.mpData[i]; | ||||
| 
 | ||||
|     for (size_t i = 0; i < b.mSize; ++i) | ||||
|         result.mpData[a.mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|     result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Mouse"; | ||||
|        | ||||
|     cout << a + b << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,86 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
| 
 | ||||
|         result.mSize = mSize + b.mSize; | ||||
|         result.mCapacity = result.mSize + 1; | ||||
|         result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| 
 | ||||
|     friend String operator+(const String& a, const String& b); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Mouse"; | ||||
|      | ||||
|     cout << a + b << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,126 @@ | |||
| /*
 | ||||
|     Оператор присваивания | ||||
| 
 | ||||
|     Оператор присваивания можно сделать только в виде метода | ||||
|     Такой метод должен  | ||||
|         - принимать один аргумент - это правый аргумент оператора присваивания,  | ||||
|         - менять объект, вызвавший оператор (то есть левый аргумент оператора присваивания) | ||||
|         - возвращать ссылку на объект, вызвавший оператор (то есть объект слева от оператора присваивания) | ||||
| 
 | ||||
| 
 | ||||
|     Почему оператор присваивания должен возвращать ссылку на левый аргумент?  | ||||
|     Чтобы оператор присваивания работал аналогично тому как работает оператор присваивания для обычных типов  | ||||
|      | ||||
|         Рассмотрим следующий пример: | ||||
| 
 | ||||
|             int a, b, c; | ||||
|             a = b = c = 123;  // все переменные станут равны 123, операторы выполняются справа налево
 | ||||
| 
 | ||||
|             (a = 1) = 2;      // a станет равной 2
 | ||||
| 
 | ||||
| 
 | ||||
|         Мы хотим, чтобы и такой код работал: | ||||
| 
 | ||||
|             String a, b, c; | ||||
|             a = b = c = "Cat"; | ||||
| 
 | ||||
|             (a = "Dog") = "Mouse"; | ||||
| 
 | ||||
| 
 | ||||
|     Прототип оператора присваивания как метода класса String должен выглядеть так: | ||||
| 
 | ||||
|         String& operator=(const String& b) | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         // Ваш код нужно написать здесь
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Mouse"; | ||||
|     String c; | ||||
| 
 | ||||
|     a = b; | ||||
|     cout << a << endl; | ||||
| 
 | ||||
|     a = b = c = "Elephant"; | ||||
|     cout << a << endl; | ||||
|     cout << b << endl; | ||||
|     cout << c << endl; | ||||
| 
 | ||||
|     (a = "Dog") = "Axolotl"; | ||||
|     cout << a << endl; | ||||
| 
 | ||||
|     a = a; | ||||
|     cout << a << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* 
 | ||||
|     Задание: | ||||
| 
 | ||||
|         1)  Написать оператор присваивания для строки String в виде метода класса String | ||||
| 
 | ||||
|             Не забудьте учесть случай: | ||||
| 
 | ||||
|                 String a = "Cat"; | ||||
|                 a = a; | ||||
| */ | ||||
|  | @ -0,0 +1,92 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Mouse"; | ||||
|     String c; | ||||
| 
 | ||||
|     a = b; | ||||
|     cout << a << endl; | ||||
| 
 | ||||
|     a = b = c = "Elephant"; | ||||
|     cout << a << endl; | ||||
|     cout << b << endl; | ||||
|     cout << c << endl; | ||||
| 
 | ||||
|     (a = "Dog") = "Axolotl"; | ||||
|     cout << a << endl; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,132 @@ | |||
| /*
 | ||||
|     Оператор присваивания сложения += | ||||
| 
 | ||||
|     Очень похож на оператор присваивания, разница только в том, каким станет левый операнд после применения этого оператора | ||||
|     К левому операнду в этом случае должна прибавиться копия правого оператора | ||||
| 
 | ||||
|     Если   a = "Cat"  ,   b = "Dog"   , то после применения   a += b   строка a будет равна "CatDog" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     Прототип оператора присваивания сложения как метода класса String должен выглядеть так: | ||||
| 
 | ||||
|         String& operator+=(const String& b) | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
| 
 | ||||
|         result.mSize = mSize + b.mSize; | ||||
|         result.mCapacity = result.mSize + 1; | ||||
|         result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     String& operator+=(const String& right) | ||||
|     { | ||||
|         // Ваш код нужно написать здесь
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Mouse"; | ||||
|     String b = "Elephant"; | ||||
| 
 | ||||
|     b += a; | ||||
| 
 | ||||
|     cout << b << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* 
 | ||||
|     Задание: | ||||
| 
 | ||||
|         1)  Написать оператор присваивания сложения для строки String в виде метода класса String | ||||
| 
 | ||||
|             Подсказка: можно использовать уже написанные операторы, чтобы реализовать этот | ||||
| */ | ||||
|  | @ -0,0 +1,110 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
| 
 | ||||
|         result.mSize = mSize + b.mSize; | ||||
|         result.mCapacity = result.mSize + 1; | ||||
|         result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     String& operator+=(const String& right) | ||||
|     { | ||||
|         *this = *this + right; | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Mouse"; | ||||
|     String b = "Elephant"; | ||||
| 
 | ||||
|     b += a; | ||||
| 
 | ||||
|     cout << b << endl; | ||||
| } | ||||
| 
 | ||||
|  | @ -0,0 +1,122 @@ | |||
| /*
 | ||||
|     По решению предыдущего занятия понятно, что операторы  +  =  и  +=  взаимосвязаны. | ||||
| 
 | ||||
|     Если реализованы операторы + и = можно, используя их, реализовать оператор  += | ||||
|     Если реализованы операторы = и += можно, используя их, реализовать оператор  + | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     String& operator+=(const String& right) | ||||
|     { | ||||
|         if (mCapacity < mSize + right.mSize + 1) | ||||
|         { | ||||
|             mCapacity = mSize + right.mSize + 1; | ||||
|             char* pNewData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|             for (size_t i = 0; i < mSize; ++i) | ||||
|                 pNewData[i] = mpData[i]; | ||||
| 
 | ||||
|             std::free(mpData); | ||||
|             mpData = pNewData; | ||||
|         } | ||||
| 
 | ||||
|         for (size_t i = 0; i < right.mSize; ++i) | ||||
|             mpData[mSize + i] = right.mpData[i]; | ||||
| 
 | ||||
|         mSize += right.mSize; | ||||
|         mpData[mSize] = '\0'; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Mouse"; | ||||
|     String b = "Elephant"; | ||||
| 
 | ||||
|     cout << a + b << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|     Задача: | ||||
| 
 | ||||
|         1)  Напишите оператор  +  , используя операторы = и += | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,108 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     String& operator+=(const String& right) | ||||
|     { | ||||
|         if (mCapacity < mSize + right.mSize + 1) | ||||
|         { | ||||
|             mCapacity = mSize + right.mSize + 1; | ||||
|             char* pNewData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|             for (size_t i = 0; i < mSize; ++i) | ||||
|                 pNewData[i] = mpData[i]; | ||||
| 
 | ||||
|             std::free(mpData); | ||||
|             mpData = pNewData; | ||||
|         } | ||||
| 
 | ||||
|         for (size_t i = 0; i < right.mSize; ++i) | ||||
|             mpData[mSize + i] = right.mpData[i]; | ||||
| 
 | ||||
|         mSize += right.mSize; | ||||
|         mpData[mSize] = '\0'; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result = *this; | ||||
|         result += b; | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Mouse"; | ||||
|     String b = "Elephant"; | ||||
| 
 | ||||
|     cout << a + b << endl; | ||||
| } | ||||
|  | @ -0,0 +1,120 @@ | |||
| /*
 | ||||
|     Операторы сравнения  ==  !=  >  >=  <  <= | ||||
| 
 | ||||
|     К строкам можно применять операторы сравнения. | ||||
| 
 | ||||
|     Очевидно, когда строки равны: должны быть равны размеры строк (mSize) и все символы от 0 до mSize | ||||
|     При этом вместимость (mCapacity) у равных строк может отличаться | ||||
| 
 | ||||
|     Как сравнивать строки на больше/меньше? В этом случае сравниваем лексикографически, то есть, по алфавиту. | ||||
|     То слово, которое находилось бы в орфографическом словаре позже и будет большим. | ||||
|     Например,  "Cat" > "Camel"  так как первые 2 буквы совпадают, а третья буква у слова Cat идёт дальше по алфавиту | ||||
| 
 | ||||
| 
 | ||||
|     Более точное сравнение такое: мы сравниваем посимвольно до первого несовпадающего символа | ||||
|     Если мы нашли первые несовпадающий символ и не дошли до конца в обоих строках, то та строка будет больше, | ||||
|     у которой этот символ больше. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     cout << std::boolalpha; | ||||
| 
 | ||||
|     String a = "Cat"; | ||||
|     String b = "Camel"; | ||||
| 
 | ||||
|     cout << (a > b) << endl; | ||||
|     cout << (a < b) << endl; | ||||
|     cout << (a == b) << endl; | ||||
|     cout << (a == a) << endl; | ||||
| 
 | ||||
| 
 | ||||
|     String c = "Catharsis"; | ||||
| 
 | ||||
|     cout << (a > c) << endl; | ||||
|     cout << (a < c) << endl; | ||||
|     cout << (a == c) << endl; | ||||
|     cout << (a != c) << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|     Задача: | ||||
| 
 | ||||
|         1)  Напишите операторы  ==  !=  >  >=  <  <=  для класса String | ||||
|             Подсказка:  можно использовать уже написанные сравнения | ||||
|             Например, если вы написали оператор > , то очень просто написать оператор <= , используя оператор > | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,140 @@ | |||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     bool operator==(const String& right) const | ||||
|     { | ||||
|         if (mSize != right.mSize) | ||||
|             return false; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return i == mSize; | ||||
|     } | ||||
| 
 | ||||
|     bool operator<(const String& right) const | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return mpData[i] < right.mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     bool operator<=(const String& right) const | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return mpData[i] <= right.mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     bool operator!=(const String& right) const | ||||
|     { | ||||
|         return !(*this == right); | ||||
|     } | ||||
| 
 | ||||
|     bool operator>(const String& right) const | ||||
|     { | ||||
|         return !(*this <= right); | ||||
|     } | ||||
| 
 | ||||
|     bool operator>=(const String& right) const | ||||
|     { | ||||
|         return !(*this < right); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     cout << std::boolalpha; | ||||
| 
 | ||||
|     String a = "Cat"; | ||||
|     String b = "Camel"; | ||||
| 
 | ||||
|     cout << (a > b) << endl; | ||||
|     cout << (a < b) << endl; | ||||
|     cout << (a == b) << endl; | ||||
|     cout << (a == a) << endl; | ||||
| 
 | ||||
| 
 | ||||
|     String c = "Catharsis"; | ||||
| 
 | ||||
|     cout << (a > c) << endl; | ||||
|     cout << (a < c) << endl; | ||||
|     cout << (a == c) << endl; | ||||
|     cout << (a != c) << endl; | ||||
| } | ||||
|  | @ -0,0 +1,122 @@ | |||
| /*
 | ||||
|     Операторы индексации  [] | ||||
| 
 | ||||
|     Чтобы получить доступ к одному символу у строки в стиле C можно использовать оператор индексации (квадратные скобочки). | ||||
|     Хотелось бы иметь такую же возможность и для нашей строки. | ||||
| 
 | ||||
|     Для этого можно перегрузить оператор индексации: | ||||
| 
 | ||||
|         char& operator[](size_t i) | ||||
| 
 | ||||
|     Этот оператор вызавется при взятии символа по индексу, например, если a это строка типа String, | ||||
| 
 | ||||
|         a[i]    будет восприниматься компилятором как   a.operator[](i) | ||||
| 
 | ||||
| 
 | ||||
|     Оператор индексации должен возвращать ссылку на символ, чтобы можно было менять соответствующий символ | ||||
| 
 | ||||
|         a[i] = 'A'; | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
| 
 | ||||
|     cout << a[0] << endl; | ||||
|     cout << a[2] << endl; | ||||
|     cout << a[4] << endl; | ||||
| 
 | ||||
| 
 | ||||
|     cout << a.at(0) << endl; | ||||
|     cout << a.at(2) << endl; | ||||
|     cout << a.at(4) << endl; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|     Задача: | ||||
| 
 | ||||
|         1)  Напишите оператор индексации для класса String | ||||
| 
 | ||||
| 
 | ||||
|         2)  Напишите метод at, который будет работать аналогично оператору индексации, только с тем отличием, что | ||||
|             если на вход приходит неправильный индекс (т. е. индекс >= mSize), то метод at должен печатать сообщение | ||||
|             об ошибке и завершать программу.  | ||||
|             Для завершения программы используйте функцию std::exit(1) из библиотеки <cstdlib>. | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,102 @@ | |||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     char& at(size_t i) | ||||
|     { | ||||
|         if (i >= mSize) | ||||
|         { | ||||
|             cout << "Error! Index is out of bounds." << endl; | ||||
|             std::exit(1); | ||||
|         } | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
| 
 | ||||
|     cout << a[0] << endl; | ||||
|     cout << a[2] << endl; | ||||
|     cout << a[4] << endl; | ||||
| 
 | ||||
| 
 | ||||
|     cout << a.at(0) << endl; | ||||
|     cout << a.at(2) << endl; | ||||
|     cout << a.at(4) << endl; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,145 @@ | |||
| /*
 | ||||
|     Напишем ещё 2 очень полезных метода: | ||||
| 
 | ||||
|         1)  reserve  -  увеличивает вместимость строки, на вход методу передаётся новая вместмость | ||||
|                         если новая вместимость меньше старой, то ничего не происходит (вместимость не уменьшается) | ||||
|                         размер и содержимое строки не меняется | ||||
| 
 | ||||
| 
 | ||||
|         2)  resize   -  изменяет размер строки, на вход методу передаётся новый размер | ||||
|                         если новый размер меньше старого, то строка усекается | ||||
|                         при необходимости увеличивает вместимость | ||||
| 
 | ||||
|     Используя эти два метода можно немного упростить код для операторов сложения и присваивания. | ||||
|     Эти методы могут быть полезны и для программиста, который будет работать с нашей строкой, поэтому сделаем их публичными. | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void reserve(size_t capacity) | ||||
|     { | ||||
|         if (capacity <= mCapacity) | ||||
|             return; | ||||
| 
 | ||||
|         mCapacity = capacity; | ||||
|         char* newData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             newData[i] = mpData[i]; | ||||
|         newData[mSize] = '\0'; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = newData; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void resize(size_t size) | ||||
|     { | ||||
|         reserve(size + 1); | ||||
|         mSize = size; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         resize(mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
|         result.resize(mSize + b.mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Dog"; | ||||
| 
 | ||||
|     cout << a.getCapacity() << endl; | ||||
|     a.reserve(10); | ||||
|     cout << a.getCapacity() << endl; | ||||
| 
 | ||||
|     cout << a + b << endl; | ||||
| 
 | ||||
| 
 | ||||
|     String c = "Sapere Aude"; | ||||
|     cout << c << endl; | ||||
| 
 | ||||
|     c.resize(6); | ||||
|     cout << c << endl; | ||||
| } | ||||
|  | @ -0,0 +1,134 @@ | |||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::cin, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void reserve(size_t capacity) | ||||
|     { | ||||
|         if (capacity <= mCapacity) | ||||
|             return; | ||||
| 
 | ||||
|         mCapacity = capacity; | ||||
|         char* newData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             newData[i] = mpData[i]; | ||||
|         newData[mSize] = '\0'; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = newData; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void resize(size_t size) | ||||
|     { | ||||
|         reserve(size + 1); | ||||
|         mSize = size; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         resize(mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
|         result.resize(mSize + b.mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = "Dog"; | ||||
| 
 | ||||
|     cout << a.getCapacity() << endl; | ||||
|     a.reserve(10); | ||||
|     cout << a.getCapacity() << endl; | ||||
| 
 | ||||
|     cout << a + b << endl; | ||||
| 
 | ||||
| 
 | ||||
|     String c = "Sapere Aude"; | ||||
|     cout << c << endl; | ||||
| 
 | ||||
|     c.resize(6); | ||||
|     cout << c << endl; | ||||
| } | ||||
|  | @ -0,0 +1,166 @@ | |||
| /*
 | ||||
|     Считывание строки с экрана | ||||
| 
 | ||||
|     Помимо удобной печати на экран с помощью объекта std::cout, хотелось бы добавить удобное считываие строки | ||||
|     с помощью объекта std::cin. | ||||
| 
 | ||||
|     Для этого нужно перегрузить оператор >> с объектами типа  std::istream  и  String, то есть написать функцию: | ||||
| 
 | ||||
|         std::istream& operator>>(std::istream& in, String& str) | ||||
| 
 | ||||
|     Эта функция должна считывать символы из стандартного входа и добавлять в строку | ||||
|     Основная проблема в том, что мы не знаем сколько символов нужно считать, поэтому нужно считывать | ||||
|     посимвольно и добавлять символы по одному в строку пока не встретим пробельный символ (' ' или '\n' или '\t') | ||||
| 
 | ||||
|     Для упрощения программы можно написать дополнительные методы | ||||
| 
 | ||||
|         void clear()               -  метод, который будет очищать строку | ||||
|                                       mSize = 0, mCapacity = 1, строка по адресу mpData равна "\0" | ||||
|      | ||||
|         void addCharacter(char c)  -  добавляет символ в конец строки | ||||
|                                       если у строки не хватает вместимости, то удваивает вместимость. | ||||
| 
 | ||||
| 
 | ||||
|     Для того, чтобы считать символ из стандартного входа можно использовать метод get класса istream | ||||
|     Этот метод возвращает следующий символ из стандартного входа | ||||
| 
 | ||||
|         char x = cin.get(); | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::cin, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void reserve(size_t capacity) | ||||
|     { | ||||
|         if (capacity <= mCapacity) | ||||
|             return; | ||||
| 
 | ||||
|         mCapacity = capacity; | ||||
|         char* newData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             newData[i] = mpData[i]; | ||||
|         newData[mSize] = '\0'; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = newData; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void resize(size_t size) | ||||
|     { | ||||
|         reserve(size + 1); | ||||
|         mSize = size; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         resize(mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
|         result.resize(mSize + b.mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a, b; | ||||
|     cin >> a >> b; | ||||
|     cout << a + b; | ||||
| 
 | ||||
|     a.addCharacter('!'); | ||||
|     cout << a << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|     Задача: | ||||
| 
 | ||||
|         1)  Напишите метод clear. | ||||
| 
 | ||||
|         2)  Напишите метод addCharacter. | ||||
| 
 | ||||
|         3)  Напишите перегруженный оператор << для считывания строки с экрана. | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,158 @@ | |||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::cin, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void reserve(size_t capacity) | ||||
|     { | ||||
|         if (capacity <= mCapacity) | ||||
|             return; | ||||
| 
 | ||||
|         mCapacity = capacity; | ||||
|         char* newData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             newData[i] = mpData[i]; | ||||
|         newData[mSize] = '\0'; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = newData; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void resize(size_t size) | ||||
|     { | ||||
|         reserve(size + 1); | ||||
|         mSize = size; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         resize(mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
|         result.resize(mSize + b.mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     void clear() | ||||
|     { | ||||
|         std::free(mpData); | ||||
| 
 | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     void addCharacter(char c) | ||||
|     { | ||||
|         if (mSize + 1 == mCapacity) | ||||
|             reserve(2 * mCapacity); | ||||
| 
 | ||||
|         mpData[mSize] = c; | ||||
|         resize(mSize + 1); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& out, const String& s)  | ||||
| { | ||||
|     out << s.cStr(); | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| std::istream& operator>>(std::istream& in, String& s)  | ||||
| { | ||||
|     s.clear(); | ||||
|     while (true) | ||||
|     { | ||||
|         char x = in.get(); | ||||
|         if (x == ' ' || x == '\n' || x == '\t') | ||||
|             break; | ||||
|         s.addCharacter(x); | ||||
|     } | ||||
|     return in; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a, b; | ||||
|     cin >> a >> b; | ||||
|     cout << a + b << endl; | ||||
| 
 | ||||
|     a.addCharacter('!'); | ||||
|     cout << a << endl; | ||||
| } | ||||
|  | @ -0,0 +1,262 @@ | |||
| /*
 | ||||
|     Собираем все методы вместе. Получилась строка, которой можно удобно пользоваться и не задумываться о выделении памяти. | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::cin, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
|     String(size_t n, char a) | ||||
|     { | ||||
|         mSize = n; | ||||
|         mCapacity = n + 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = a; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     void reserve(size_t capacity) | ||||
|     { | ||||
|         if (capacity <= mCapacity) | ||||
|             return; | ||||
| 
 | ||||
|         mCapacity = capacity; | ||||
|         char* newData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             newData[i] = mpData[i]; | ||||
|         newData[mSize] = '\0'; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = newData; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void resize(size_t size) | ||||
|     { | ||||
|         reserve(size + 1); | ||||
|         mSize = size; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         resize(mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
|         result.resize(mSize + b.mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     String& operator+=(const String& right) | ||||
|     { | ||||
|         *this = *this + right; | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     bool operator==(const String& right) const | ||||
|     { | ||||
|         if (mSize != right.mSize) | ||||
|             return false; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return i == mSize; | ||||
|     } | ||||
| 
 | ||||
|     bool operator<(const String& right) const | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return mpData[i] < right.mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     bool operator<=(const String& right) const | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return mpData[i] <= right.mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     bool operator!=(const String& right) const | ||||
|     { | ||||
|         return !(*this == right); | ||||
|     } | ||||
| 
 | ||||
|     bool operator>(const String& right) const | ||||
|     { | ||||
|         return !(*this <= right); | ||||
|     } | ||||
| 
 | ||||
|     bool operator>=(const String& right) const | ||||
|     { | ||||
|         return !(*this < right); | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     char& at(size_t i) | ||||
|     { | ||||
|         if (i >= mSize) | ||||
|         { | ||||
|             cout << "Error! Index is out of bounds." << endl; | ||||
|             std::exit(1); | ||||
|         } | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     void clear() | ||||
|     { | ||||
|         std::free(mpData); | ||||
| 
 | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     void addCharacter(char c) | ||||
|     { | ||||
|         if (mSize + 1 == mCapacity) | ||||
|             reserve(2 * mCapacity); | ||||
| 
 | ||||
|         mpData[mSize] = c; | ||||
|         resize(mSize + 1); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& out, const String& s)  | ||||
| { | ||||
|     out << s.cStr(); | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| std::istream& operator>>(std::istream& in, String& s)  | ||||
| { | ||||
|     s.clear(); | ||||
|     while (true) | ||||
|     { | ||||
|         char x = in.get(); | ||||
|         if (x == ' ' || x == '\n' || x == '\t') | ||||
|             break; | ||||
|         s.addCharacter(x); | ||||
|     } | ||||
|     return in; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Mouse"; | ||||
|     String b; | ||||
|     cin >> b; | ||||
|     String c = b; | ||||
| 
 | ||||
|     if (a + c == "MouseLion") | ||||
|         cout << "Yes" << endl; | ||||
|     else | ||||
|         cout << "No" << endl; | ||||
| 
 | ||||
| 
 | ||||
|     if (a > "Mice") | ||||
|         cout << "Yes" << endl; | ||||
|     else | ||||
|         cout << "No" << endl; | ||||
| 
 | ||||
| 
 | ||||
|     c[0] = 'P'; | ||||
|     cout << c << endl; | ||||
| 
 | ||||
|     c += a; | ||||
|     cout << c << endl; | ||||
| 
 | ||||
|     c = c + String(10, 'q'); | ||||
|     cout << c << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|     Задача: | ||||
| 
 | ||||
| 
 | ||||
|         1)  Напищите программу, которая будет считывать слова (используйте cin) в бесконечном цикле и каждый | ||||
|             раз печатать сумму всех слов. Например, если пользователь ввёл Hello, то программа должна напечатать | ||||
|             Hello и запросить следующее слово. Если затем пользователь введёт World, то программа должна будет | ||||
|             напечатать HelloWorld и запросить следуещее слово и так далее. | ||||
|             Программа должна останавливаться если пользователь ввёл слово "quit". | ||||
| */ | ||||
|  | @ -0,0 +1,233 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::cin, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; i++) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() : String("") {} | ||||
|     String(const String& s) : String(s.cStr()) {} | ||||
| 
 | ||||
|     String(size_t n, char a) | ||||
|     { | ||||
|         mSize = n; | ||||
|         mCapacity = n + 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = a; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     void reserve(size_t capacity) | ||||
|     { | ||||
|         if (capacity <= mCapacity) | ||||
|             return; | ||||
| 
 | ||||
|         mCapacity = capacity; | ||||
|         char* newData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             newData[i] = mpData[i]; | ||||
|         newData[mSize] = '\0'; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = newData; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void resize(size_t size) | ||||
|     { | ||||
|         reserve(size + 1); | ||||
|         mSize = size; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         resize(mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String operator+(const String& b) | ||||
|     { | ||||
|         String result; | ||||
|         result.resize(mSize + b.mSize); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             result.mpData[i] = mpData[i]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < b.mSize; ++i) | ||||
|             result.mpData[mSize + i] = b.mpData[i]; | ||||
| 
 | ||||
|         result.mpData[result.mSize] = '\0'; | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     String& operator+=(const String& right) | ||||
|     { | ||||
|         *this = *this + right; | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     bool operator==(const String& right) const | ||||
|     { | ||||
|         if (mSize != right.mSize) | ||||
|             return false; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return i == mSize; | ||||
|     } | ||||
| 
 | ||||
|     bool operator<(const String& right) const | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return mpData[i] < right.mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     bool operator<=(const String& right) const | ||||
|     { | ||||
|         size_t i = 0; | ||||
|         while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i]) | ||||
|             i++; | ||||
| 
 | ||||
|         return mpData[i] <= right.mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     bool operator!=(const String& right) const | ||||
|     { | ||||
|         return !(*this == right); | ||||
|     } | ||||
| 
 | ||||
|     bool operator>(const String& right) const | ||||
|     { | ||||
|         return !(*this <= right); | ||||
|     } | ||||
| 
 | ||||
|     bool operator>=(const String& right) const | ||||
|     { | ||||
|         return !(*this < right); | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     char& at(size_t i) | ||||
|     { | ||||
|         if (i >= mSize) | ||||
|         { | ||||
|             cout << "Error! Index is out of bounds." << endl; | ||||
|             std::exit(1); | ||||
|         } | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void clear() | ||||
|     { | ||||
|         std::free(mpData); | ||||
| 
 | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     void addCharacter(char c) | ||||
|     { | ||||
|         if (mSize + 1 == mCapacity) | ||||
|             reserve(2 * mCapacity); | ||||
| 
 | ||||
|         mpData[mSize] = c; | ||||
|         resize(mSize + 1); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& out, const String& s)  | ||||
| { | ||||
|     out << s.cStr(); | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| std::istream& operator>>(std::istream& in, String& s)  | ||||
| { | ||||
|     s.clear(); | ||||
|     while (true) | ||||
|     { | ||||
|         char x = in.get(); | ||||
|         if (x == ' ' || x == '\n' || x == '\t') | ||||
|             break; | ||||
|         s.addCharacter(x); | ||||
|     } | ||||
|     return in; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String all; | ||||
|     String nextWord; | ||||
| 
 | ||||
|     while (true) | ||||
|     { | ||||
|         cin >> nextWord; | ||||
|         if (nextWord == "quit") | ||||
|             break; | ||||
| 
 | ||||
|         all += nextWord; | ||||
|         cout << all << endl; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,142 @@ | |||
| /*
 | ||||
|     Рассмотрим при каких условиях происходит вызов того или иного метода. | ||||
| 
 | ||||
|     Для этого будем использовать класс String, в котором была добавлена печать на экран для конструкторов,  | ||||
|     деструктора и оператора присваивания. | ||||
|     Например, конструктор по умолчанию будет печатать Default Constructor и т. д. | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "String Constructor from const char*  (" << str << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; ++i) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "String Default Constructor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char)); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(const String& s)  | ||||
|     { | ||||
|         cout << "String Copy Constructor  (" << s.mpData << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = mSize + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "String Destructor  (" << mpData << ")" << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         cout << "String Assignment Operator  (" << right.mpData << ")" << endl; | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String b = a; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|     Задачи: | ||||
| 
 | ||||
|         1)  Какие методы вызовутся в строке | ||||
| 
 | ||||
|                 String a = "Cat"; | ||||
| 
 | ||||
|             Выберите один из вариантов: | ||||
| 
 | ||||
|                 а)  Только конструктор из const char* | ||||
|                 б)  Только оператор присваивания | ||||
|                 в)  И конструктор из const char* и оператор присваивания | ||||
| 
 | ||||
| 
 | ||||
|         2)  Какие методы вызовутся в строке | ||||
| 
 | ||||
|                 String b = a; | ||||
| 
 | ||||
|             Выберите один из вариантов: | ||||
| 
 | ||||
|                 а)  Только конструктор копирования | ||||
|                 б)  Только оператор присваивания | ||||
|                 в)  И конструктор копирования и оператор присваивания | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         3)  Проверьте ваши догадки скомпилировав и запустив программу | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,121 @@ | |||
| /*
 | ||||
|     Рассмотрим при каких условиях происходит вызов того или иного метода. | ||||
| 
 | ||||
|     Для этого будем использовать класс String, в котором была добавлена печать на экран для конструкторов,  | ||||
|     деструктора и оператора присваивания. | ||||
|     Например, конструктор по умолчанию будет печатать Default Constructor и т. д. | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "String Constructor from const char*  (" << str << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; ++i) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "String Default Constructor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char)); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(const String& s)  | ||||
|     { | ||||
|         cout << "String Copy Constructor  (" << s.mpData << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = mSize + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "String Destructor  (" << mpData << ")" << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         cout << "String Assignment Operator  (" << right.mpData << ")" << endl; | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     String c; | ||||
|     c = a; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|     Задачи: | ||||
| 
 | ||||
|         1)  Какие методы класса String вызовутся в данной программе. | ||||
| 
 | ||||
|         2)  Проверьте ваши догадки, скомпилировав и запустив программу | ||||
| */ | ||||
|  | @ -0,0 +1,36 @@ | |||
| /*
 | ||||
|     Решения: | ||||
| 
 | ||||
|         1)  String a = "Cat"; | ||||
| 
 | ||||
|             Будет вызван только конструктор из const char* | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         2)  String b = a; | ||||
| 
 | ||||
|             Будет вызван только конструктор копирования | ||||
| 
 | ||||
|     Несмотря на то, что в этих выражениях присутствует символ  =  оператор присваивания в этих случаях не вызывается. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         3)  String c; | ||||
|             c = a; | ||||
| 
 | ||||
|             Будет вызван конструктор по умолчанию в строке  String c; | ||||
|             А потом будет вызван оператор присваивания в строке  c = a; | ||||
| 
 | ||||
| 
 | ||||
|     Получается символ  =  может использоваться для обозначения двух разных вещей: инициализации и присваивания. | ||||
| 
 | ||||
| 
 | ||||
|             String a = "Cat"; // Инициализация строкой "Cat"    (вызов коструктора от const char*)
 | ||||
| 
 | ||||
|             String b = a;     // Инициализация объектом a       (вызов коструктора копирования)
 | ||||
| 
 | ||||
|             String c;         // Инициализация по умолчанию     (вызов конструктора по умолчанию)
 | ||||
|             c = a;            // Присваивание                   (вызов метода operator=)
 | ||||
|      | ||||
| */ | ||||
|  | @ -0,0 +1,135 @@ | |||
| /*
 | ||||
|     Посмотрим какие особые методы вызываются при передаче объекта в функцию. | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "String Constructor from const char*  (" << str << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; ++i) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "String Default Constructor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char)); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(const String& s)  | ||||
|     { | ||||
|         cout << "String Copy Constructor  (" << s.mpData << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = mSize + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "String Destructor  (" << mpData << ")" << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         cout << "String Assignment Operator  (" << right.mpData << ")" << endl; | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void print(String s) | ||||
| { | ||||
|     cout << s << endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     print(a); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|     Задачи: | ||||
| 
 | ||||
|         1)  Какие методы класса String вызовутся в данной программе. | ||||
| 
 | ||||
| 
 | ||||
|         2)  Проверьте ваши догадки скомпилировав и запустив программу | ||||
| 
 | ||||
| 
 | ||||
|         3)  Что если мы будем передавать объект String в функцию print не по значению, а по ссылке, то есть изменим | ||||
|             функцию print на следующую: | ||||
| 
 | ||||
|                 void print(const String& s) | ||||
|                 { | ||||
|                     cout << s << endl; | ||||
|                 } | ||||
| 
 | ||||
|             Какие методы будут вызваны теперь? | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,64 @@ | |||
| /*
 | ||||
|     Решения: | ||||
|      | ||||
|     1)  В случае: | ||||
| 
 | ||||
|             void print(String s) | ||||
|             { | ||||
|                 cout << s << endl; | ||||
|             } | ||||
| 
 | ||||
|             int main()  | ||||
|             { | ||||
|                 String a = "Cat"; | ||||
|                 print(a); | ||||
|             } | ||||
| 
 | ||||
|         Вызовутся следующие методы: | ||||
| 
 | ||||
|             1)  Конструктор строки из "Cat" | ||||
|              | ||||
| 
 | ||||
|             2)  При передаче объекта в функцию по значению, он должен быть скопирован.  | ||||
|                 Соответственно при вызове  print(a)  объект a должен скопироваться в объект s функции print. | ||||
|                 Для обычных типов вроде int тут бы произошло побайтовое копирование, но для классов вызывается конструктор копирования. | ||||
| 
 | ||||
| 
 | ||||
|             3)  Внутри функции print объект s печатается на экран. Затем мы выходим из функции print и уничтожаем все локальные объекты этой функции. | ||||
|                 Соответственно вызовется деструктор для объекта s. | ||||
| 
 | ||||
| 
 | ||||
|             4)  Затем мы выходим из функции main и уничтожаем все объекты, локальные для функции main. | ||||
|                 Соответственно вызовется деструктор для объекта a. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     3)  В случае: | ||||
| 
 | ||||
|             void print(const String& s) | ||||
|             { | ||||
|                 cout << s << endl; | ||||
|             } | ||||
| 
 | ||||
|             int main()  | ||||
|             { | ||||
|                 String a = "Cat"; | ||||
|                 print(a); | ||||
|             } | ||||
| 
 | ||||
|         Вызовутся следующие методы: | ||||
| 
 | ||||
|             1)  Конструктор строки из "Cat" | ||||
|      | ||||
|              | ||||
|                 При передаче объекта в функцию по ссылке, этот объект в функцию не копируется. | ||||
|                 Поэтому никаких конструкторов копирования не вызывается. | ||||
| 
 | ||||
| 
 | ||||
|             2)  Деструктор для строки a из функии main. | ||||
| 
 | ||||
| 
 | ||||
|         Получается, что обычно передавать объекты в функции более эффективно по ссылке, а не по значению. | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,131 @@ | |||
| /*
 | ||||
|     Особые методы при передачах в функцию | ||||
| 
 | ||||
|     Посмотрим какие особые методы вызываются при передаче объекта в функцию | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "String Constructor from const char*  (" << str << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; ++i) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "String Default Constructor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char)); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(const String& s)  | ||||
|     { | ||||
|         cout << "String Copy Constructor  (" << s.mpData << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = mSize + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "String Destructor  (" << mpData << ")" << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         cout << "String Assignment Operator  (" << right.mpData << ")" << endl; | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void changeFirstLetter(String s) | ||||
| { | ||||
|     s[0] = 'B'; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     cout << a << endl; | ||||
| 
 | ||||
|     changeFirstLetter(a); | ||||
|     cout << a << endl; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|     Задачи: | ||||
| 
 | ||||
|         1)  Какие методы класса String вызовутся в данной программе. | ||||
| 
 | ||||
|         2)  Проверьте ваши догадки скомпилировав и запустив программу | ||||
| 
 | ||||
|         3)  Функция changeFirstLetter должна была менять первую букву нашей строки на букву 'B', но это не происходит и | ||||
|             строка  a  после вызова  changeFirstLetter(a)  остаётся неизменной. | ||||
|             Почему это происходит и как изменить функцию  changeFirstLetter  чтобы она меняла первую букву переданной строки. | ||||
| */ | ||||
|  | @ -0,0 +1,136 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "String Constructor from const char*  (" << str << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; ++i) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "String Default Constructor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char)); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(const String& s)  | ||||
|     { | ||||
|         cout << "String Copy Constructor  (" << s.mpData << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = mSize + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "String Destructor  (" << mpData << ")" << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         cout << "String Assignment Operator  (" << right.mpData << ")" << endl; | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void changeFirstLetter(String& s) | ||||
| { | ||||
|     s[0] = 'B'; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
|     cout << a << endl; | ||||
| 
 | ||||
|     changeFirstLetter(a); | ||||
|     cout << a << endl; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|     Решение: | ||||
|          | ||||
|         В такую функцию: | ||||
| 
 | ||||
|             void changeFirstLetter(String s) | ||||
|             { | ||||
|                 s[0] = 'B'; | ||||
|             } | ||||
| 
 | ||||
|         строка передавалась по значению и, следовательно, происходило копирование этой строки в объект s функции changeFirstLetter. | ||||
|         Функция changeFirstLetter меняла первую букву копии нашей строки, но оригинальная строка не менялась. | ||||
| 
 | ||||
|          | ||||
|         Для того, чтобы функция changeFirstLetter меняла оригинальную строку ей нужно передавать объект не по значению, а по ссылке вот так: | ||||
| 
 | ||||
|             void changeFirstLetter(String& s) | ||||
|             { | ||||
|                 s[0] = 'B'; | ||||
|             } | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,149 @@ | |||
| /*
 | ||||
|     Различный синтаксис вызова конструкторов | ||||
| */ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "String Constructor from const char*  (" << str << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; ++i) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "String Default Constructor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char)); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(const String& s)  | ||||
|     { | ||||
|         cout << "String Copy Constructor  (" << s.mpData << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = mSize + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "String Destructor  (" << mpData << ")" << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         cout << "String Assignment Operator  (" << right.mpData << ")" << endl; | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a = "Cat"; | ||||
| 
 | ||||
|     String b = String("Dog"); | ||||
| 
 | ||||
|     String c("Mouse"); | ||||
| 
 | ||||
|     String d = {"Tiger"}; | ||||
| 
 | ||||
|     String e = String{"Axolotl"}; | ||||
| 
 | ||||
|     String f {"Lion"}; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|     Ввиду того, что язык C++ имеет длинную историю, на протяжении которой в язык добавлялись новые возможности, | ||||
|     в языке существует множество способов сделать одно и то же разными способами. | ||||
| 
 | ||||
|     Один из ярких примеров этого является инициализация объекта. В этом примере создаются 6 строк. Синтаксис различается,  | ||||
|     но в данном случае все эти строки по сути делают одно и то же: cоздают объект с помощью конструктора от const char*. | ||||
|     При этом не вызывается никаких конструкторов копирования или операторов присваивания. | ||||
| 
 | ||||
|     В современном языке C++ предпочтительным способом инициализации является вариант f: | ||||
| 
 | ||||
|         String f {"Lion"}; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     Задачи: | ||||
| 
 | ||||
|         1)  Что напечатает данная программа? | ||||
|             В каком порядке вызовутся конструкторы и в каком порядке вызовутся деструкторы? | ||||
| 
 | ||||
|         2)  Скомпилируйте программу и запустите, чтобы проверить ваши догадки. | ||||
| 
 | ||||
|         3)  Создайте 5 объектов типа String с помощью конструктора по умолчанию, используя разный синтаксис вызова конструктора. | ||||
| 
 | ||||
|         4)  Пусть есть объект x типа String: | ||||
| 
 | ||||
|                 String x = "Cat"; | ||||
| 
 | ||||
|             Создайте 6 объектов типа String с помощью конструктора копирования, используя разный синтаксис вызова конструктора. | ||||
|             Все новые объекты должны копировать объект x. | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,124 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "String Constructor from const char*  (" << str << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; ++i) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "String Default Constructor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char)); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(const String& s)  | ||||
|     { | ||||
|         cout << "String Copy Constructor  (" << s.mpData << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = mSize + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "String Destructor  (" << mpData << ")" << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         cout << "String Assignment Operator  (" << right.mpData << ")" << endl; | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String a; | ||||
| 
 | ||||
|     String b = String(); | ||||
| 
 | ||||
|     // String c();
 | ||||
| 
 | ||||
|     String d = {}; | ||||
| 
 | ||||
|     String e = String{}; | ||||
| 
 | ||||
|     String f {}; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|     Аналогично есть множество вариантов синтаксиса вызова конструктора по умолчанию. | ||||
| 
 | ||||
|     Только такой вариант вызова конструктора не работает: | ||||
| 
 | ||||
|         String c(); | ||||
| 
 | ||||
|     Потому что в этом случае компилятор считает, что это объявление функции по имени c, которая ничего не принимает и возвращает объект типа String. | ||||
| 
 | ||||
| */ | ||||
|  | @ -0,0 +1,116 @@ | |||
| #include <iostream> | ||||
| #include <cstdlib> | ||||
| using std::cout, std::endl, std::size_t; | ||||
| 
 | ||||
| 
 | ||||
| class String  | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     size_t mSize; | ||||
|     size_t mCapacity; | ||||
|     char* mpData; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     String(const char* str)  | ||||
|     { | ||||
|         cout << "String Constructor from const char*  (" << str << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         while (str[i] != '\0') | ||||
|             i++; | ||||
|         mSize = i; | ||||
|         mCapacity = i + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; str[i]; ++i) | ||||
|             mpData[i] = str[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String() | ||||
|     { | ||||
|         cout << "String Default Constructor" << endl; | ||||
|         mSize = 0; | ||||
|         mCapacity = 1; | ||||
|         mpData = (char*)std::malloc(sizeof(char)); | ||||
|         mpData[0] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     String(const String& s)  | ||||
|     { | ||||
|         cout << "String Copy Constructor  (" << s.mpData << ")" << endl; | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         mSize = s.mSize; | ||||
|         mCapacity = mSize + 1; | ||||
| 
 | ||||
|         mpData = (char*)std::malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i < mSize; ++i) | ||||
|             mpData[i] = s.mpData[i]; | ||||
|         mpData[mSize] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     ~String() | ||||
|     { | ||||
|         cout << "String Destructor  (" << mpData << ")" << endl; | ||||
|         std::free(mpData); | ||||
|     } | ||||
| 
 | ||||
|     String& operator=(const String& right) | ||||
|     { | ||||
|         cout << "String Assignment Operator  (" << right.mpData << ")" << endl; | ||||
|         if (this == &right) | ||||
|             return *this; | ||||
| 
 | ||||
| 
 | ||||
|         mSize = right.mSize; | ||||
|         mCapacity = right.mCapacity; | ||||
| 
 | ||||
|         std::free(mpData); | ||||
|         mpData = (char*)malloc(sizeof(char) * mCapacity); | ||||
| 
 | ||||
|         for (size_t i = 0; i <= mSize; ++i) | ||||
|             mpData[i] = right.mpData[i]; | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     char& operator[](size_t i) | ||||
|     { | ||||
|         return mpData[i]; | ||||
|     } | ||||
| 
 | ||||
|     size_t getSize()        const   {return mSize;} | ||||
|     size_t getCapacity()    const   {return mCapacity;} | ||||
|     const char* cStr()      const   {return mpData;} | ||||
| }; | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const String& right)  | ||||
| { | ||||
|     left << right.cStr(); | ||||
|     return left; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     String x = "Cat"; | ||||
| 
 | ||||
| 
 | ||||
|     String a = x; | ||||
| 
 | ||||
|     String b = String(x); | ||||
| 
 | ||||
|     String c(x); | ||||
| 
 | ||||
|     String d = {x}; | ||||
| 
 | ||||
|     String e = String{x}; | ||||
| 
 | ||||
|     String f {x}; | ||||
| } | ||||
		Reference in a new issue