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