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