Скачиваний:
37
Добавлен:
10.09.2019
Размер:
8.26 Кб
Скачать
#include <iostream>
#include <stdexcept>

using std::cin;
using std::cout;
using std::endl;

// Динамический одномерный вектор-массив
template <class T>
class DynArray {
 private:

    // Текущий размер массива
    size_t n_;
    // Резервируемый размер массива (m_ >= n_)
    size_t m_ = 10;
    // Указатель на массив из m_ элементов
    T *values_ = nullptr;

 protected:

    // Стандартное количество резервируемых элементов в массиве
    size_t standart = 10;

 public:

    // Конструктор
    explicit DynArray(size_t n = 0) : n_(n) {
        if (n >= m_) {
            m_ = n * 2;
        }
        values_ = new T[m_] {0};
    }

    // Конструктор копирования
    DynArray(const DynArray &da) : DynArray(da.n_) {
        n_ = da.n_;
        std::copy(da.values_, da.values_ + n_, values_);
    }

    // Оператор копирования
    DynArray &operator=(const DynArray &da) {
        DynArray temp(da);
        swap(*this, temp);
        return *this;
    }

    // Конструктор перемещения
    DynArray(DynArray &&da) noexcept {
        n_ = da.n_, m_ = da.m_, values_ = da.values_, standart = da.standart;
        da.n_ = 0, da.m_ = 0, da.values_ = nullptr;
    }

    // Оператор перемещения
    DynArray &operator=(DynArray &&da) noexcept {
        if (this != &da) {
            swap(*this, da);
            delete[] da.values_, da.values_ = nullptr;
            da.n_ = 0, da.m_ = 0;
        }
        return *this;
    }

    // Деструктор
    virtual ~DynArray() {
        delete[] values_;
    }

    // Оператор получения элемента по индексу I
    T &operator[](size_t i) {
        return values_[i];
    }

    // [static] Получение размера массива
    static size_t size(const DynArray &da) {
        return da.n_;
    }

    // Добавление K элементов из массива DA в конец
    void add(const DynArray &da, const size_t &k) {
        size_t mn = std::min(DynArray::size(da), k);
        for (size_t i = 0; i < k; ++i) {
            push_back(da.values_[i]);
        }
    }

    // Вставка элемента D в позицию K
    void insert(const T &d, const size_t &k) noexcept(false) {
        if (k == 0) {
            push_front(d);
            return;
        } else if (k == n_) {
            push_back(d);
            return;
        } else if (k > 0 && k < n_) {
            push_back(d);
            T t = values_[k], p;
            for (size_t i = k; i < n_; ++i) {
                p = values_[i], values_[i] = t, t = p;
            }
            values_[k] = d;
            return;
        }
        throw std::out_of_range("DynArray. Method insert. Out of range");
    }

    // Добавление элемента D в конец
    void push_back(const T &d) {
        if (n_ < m_) {
            values_[n_] = d, ++n_;
            return;
        }
        T *b = values_;
        values_ = new T[m_ * 2] {0};
        std::copy(b, b + n_, values_);
        delete[] b;
        m_ *= 2;
    }

    // Добавление элемента D в начало
    void push_front(const T &d) {
        push_back(d);
        T t = values_[0], p;
        for (size_t i = 1; i < n_; ++i) {
            p = values_[i], values_[i] = t, t = p;
        }
        values_[0] = d;
    }

    // Очистка массива
    void clear() {
        delete[] values_;
        values_ = new T[standart] {0};
        n_ = 0, m_ = standart;
    }

    // Получение размера массива
    size_t size() const noexcept { return n_; }

    // Пустой ли массив
    bool empty() const noexcept { return n_ == 0; }

    // Удаление элемента с индексом I
    T erase(size_t i) noexcept(false) {
        if (n_ > 0 && i < n_) {
            T d = 0;
            d = values_[i];
            std::copy(values_ + i + 1, values_ + n_, values_ + i);
            --n_;
            return d;
        }
        throw std::out_of_range("DynArray. Method erase. Out of range");
    }

    // Удаление первого (нулевого) элемента
    T pop_front() {
        return erase(0);
    }

    // Удаление последнего элемента
    T pop_back() {
        T d = 0;
        if (n_ > 0) {
            d = values_[n_ - 1], --n_;
        }
        return d;
    }

    // Оператор приведения к типу bool
    explicit operator bool () {
        return n_ != 0;
    }

    // Дружественный оператор для вывода массива в ostream (cout, ...)
    friend std::ostream &operator<<(std::ostream &os, const DynArray &da) {
        if (da.n_ > 0) {
            os << da.values_[0];
            for (size_t i = 1; i < da.n_; ++i) {
                os << ' ' << da.values_[i];
            }
        }
        return os;
    }

    friend void swap(DynArray &first, DynArray &second) noexcept {
        std::swap(first.standart, second.standart);
        std::swap(first.values_, second.values_);
        std::swap(first.m_, second.m_);
        std::swap(first.n_, second.n_);
    }
};

int main() {
    DynArray<double> da, db(5);
    da.push_back(1);
    da.push_back(2);
    da.push_back(3);
    da.push_back(4);
    da.push_front(1);
    da.push_front(2);
    da.push_front(3);
    da.push_front(4);
    cout << "First array (after push_back and push_front): " << da << endl;
    db.add(da, da.size());
    cout << "Second array (5 empty + method add from first array): " << db << endl;
    for (size_t i = 0; i < da.size(); ++i) {
        da[i] = i + 1;
    }
    cout << "First array (after reinitialize): " << da << endl;
    cout << "First array size: " << da.size() << " (isEmpty ? " << ( da.empty() ? "TRUE" : "FALSE" ) << ")\n";
    da.clear();
    cout << "First array cleared: " << da << endl;
    cout << "First array size: " << da.size() << " (isEmpty ? " << ( da.empty() ? "TRUE" : "FALSE" ) << ")\n";
    db.insert(-6, 2);
    db.insert(-7, 2);
    db.insert(-8, 2);
    db.insert(-9, 2);
    cout << "Second array (insert -6, -7, -8, -9): " << db << endl;
    cout << "Second array (erased " << db.erase(2) << ")\n";
    cout << "Second array (erased " << db.erase(2) << ")\n";
    cout << "Second array (erased " << db.erase(2) << ")\n";
    cout << "Second array (erased " << db.erase(2) << ")\n";
    cout << "Second array: " << db << endl;
    cout << "Second array (pop_front " << db.pop_front() << ")\n";
    cout << "Second array (pop_front " << db.pop_front() << ")\n";
    cout << "Second array: " << db << endl;
    cout << "Second array (pop_back " << db.pop_back() << ")\n";
    cout << "Second array (pop_back " << db.pop_back() << ")\n";
    cout << "[Input] Old array: " << db << endl;
    DynArray<double> dc(db); // Конструктор копирования
    cout << "[Output] Old array (after copy): " << db << endl;
    cout << "[Output] New array (after copy construct): " << dc << endl;
    cout << "[Input] Old array: " << dc << endl;
    db = dc; // Оператор копирования
    cout << "[Output] Old array (after copy): " << dc << endl;
    cout << "[Output] New array (after copy assignment): " << db << endl;
    cout << "[Input] Old array: " << db << endl;
    DynArray<double> df(std::move(db)); // Конструктор перемещения
    cout << "[Output] Old array (after move): " << db << endl;
    cout << "[Output] New array (after move construct): " << df << endl;
    cout << "[Input] Old array: " << df << endl;
    db = std::move(df); // Оператор перемещения
    cout << "[Output] Old array (after move): " << df << endl;
    cout << "[Output] New array (after move assignment): " << db << endl;
}
Соседние файлы в папке Решения лабораторных работ (местами есть ошибки)