/*
    Операторы индексации  []

    Чтобы получить доступ к одному символу у строки в стиле 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>.

*/