/* Создадим строку, которая при создании (т.е в конструкторе) будет автоматически выделять необходимую память в Куче. В чём-то реализация этой строки будет похожа на реализацию динамического массива из прошлого семестра. У класса строки 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 #include 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; */