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

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

// Класс «Массив»
class SimpleArray {
 private:

    // Размер массива
    size_t n_ = 0;
    // Число зарезервированных элементов (m_ >= n_)
    size_t m_ = 0;
    // Указатель на массив
    double *values_ = nullptr;

 public:

    // Конструктор
    explicit SimpleArray(size_t n = 0) : n_(n), m_(n) {
        values_ = new double[m_] {0};
    }

    // Конструктор копирования
    SimpleArray(const SimpleArray &arg) : n_(arg.n_), m_(arg.m_) {
        if (m_ > 0) {
            values_ = new double[m_] {0};
            if (n_ > 0) {
                std::copy(arg.values_, arg.values_ + arg.n_, values_);
            }
        }
    }

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

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

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

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

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

    // Получение элемента массива по индексу (не вызывает исключения)
    double &operator[](size_t idx) {
        return values_[idx];
    }

    // Объединение двух массивов
    SimpleArray merge(const SimpleArray &arg) const {
        SimpleArray temp(n_ + arg.n_);
        if (n_) {
            std::copy(values_, values_ + n_, temp.values_);
        }
        if (arg.n_) {
            std::copy(arg.values_, arg.values_ + arg.n_, temp.values_ + n_);
        }
        return temp;
    }

    // Добавление элемента в конец массива
    void push_back(const double &elem) {
        if (n_ < m_) { // Если текущий размер меньше числа зарезервированных элементов
            values_[n_] = elem; // Заполняем новый элемент
            ++n_;
            return;
        }
        double *temp = values_; // Иначе генерируем новый массив
        if (m_ == 0) {
            m_ = 1;
        }
        m_ *= 2; // С размером вдвое большим предыдущего
        values_ = new double[m_];
        if (temp != nullptr) { // Если прежний массив существовал, то копируем из него значения
            std::copy(temp, temp + n_, values_);
        }
        values_[n_] = elem; // Заполняем новый элемент
        delete[] temp;
        ++n_;
    }

    // Удаление count элементов с позиции idx
    void erase(size_t idx, size_t count) noexcept(false) {
        if (idx + count <= n_) {
            std::copy(values_ + idx + count, values_ + n_, values_ + idx); // Сдвиг конца массива влево ('удаление')
            n_ -= count;
            return;
        }
        throw std::invalid_argument("SimpleArray. Method erase. Index + Count > N");
    }

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

    // Произведение элементов массива и на число d
    long double mul(double d = 1) const {
        for (size_t i = 0; i < n_; ++i) {
            d *= values_[i];
        }
        return d;
    }

    // Максимальный элемент массива
    double max() const {
        double mx = 0;
        if (n_ > 0) {
            mx = values_[0];
            for (size_t i = 1; i < n_; ++i) {
                if (values_[i] > mx) {
                    mx = values_[i];
                }
            }
        }
        return mx;
    }

    // Минимальный элемент массива
    double min() const {
        double mn = 0;
        if (n_ > 0) {
            mn = values_[0];
            for (size_t i = 1; i < n_; ++i) {
                if (values_[i] < mn) {
                    mn = values_[i];
                }
            }
        }
        return mn;
    }

    // Вставка одного массива в заданную позицию другого
    SimpleArray insert(const SimpleArray &arg, size_t idx) const noexcept(false) {
        if (idx <= n_) {
            SimpleArray result(n_ + arg.n_); // (0, 0, 0, 0, 0, 0, 0)
            std::copy(values_, values_ + idx, result.values_); // (1, 2, 0, 0, 0, 0, 0)
            std::copy(arg.values_, arg.values_ + arg.n_, result.values_ + idx); // (1, 2, -3, -4, 0, 0, 0)
            std::copy(values_ + idx, values_ + n_, result.values_ + idx + arg.n_); // (1, 2, -3, -4, 5, 6, 7)
            return result;
        }
        throw std::invalid_argument("SimpleArray. Method insert. Index > N");
    }

    // Умножение всех элементов массива на заданное число
    SimpleArray operator*(const double &d) const {
        SimpleArray result(*this);
        for (size_t i = 0; i < n_; ++i) {
            result.values_[i] *= d;
        }
        return result;
    }

    // Деление всех элементов массива на заданное число
    SimpleArray operator/(const double &d) const {
        return ( *this * ( 1. / d ) );
    }

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

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

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

int main() {
    const size_t N1 = 2, N2 = 5;
    // Создание массивов
    SimpleArray massA(N1), massB(N2);
    // Вывод массивов и их размеров
    cout << "Array A: " << massA << " (size: " << massA.size() << ")\n";
    cout << "Array B: " << massB << " (size: " << massB.size() << ")\n";
    // Заполнение массивов
    for (size_t i = 0; i < N1; ++i) { massA[i] = rand() % 100; }
    for (size_t i = 0; i < N2; ++i) { massB[i] = rand() % 100; }
    // Вывод массивов
    cout << "Array A: " << massA << " (size: " << massA.size() << ")\n";
    cout << "Array B: " << massB << " (size: " << massB.size() << ")\n" << endl;
    // Конструктор копирования
    SimpleArray massC(massB);
    cout << "1. Copy constructor:\n";
    cout << "Array B: " << massB << " (size: " << massB.size() << ")\n";
    cout << "Array C: " << massC << " (size: " << massC.size() << ")\n";
    // Оператор копирования
    massC = massA;
    cout << "2. Copy assignment:\n";
    cout << "Array A: " << massA << " (size: " << massA.size() << ")\n";
    cout << "Array C: " << massC << " (size: " << massC.size() << ")\n";
    // Конструктор перемещения
    SimpleArray massD(std::move(massB));
    cout << "3. Move constructor:\n";
    cout << "Array B: " << massB << " (size: " << massB.size() << ")\n";
    cout << "Array D: " << massD << " (size: " << massD.size() << ")\n";
    // Оператор перемещения
    massD = std::move(massA);
    cout << "4. Move assignment:\n";
    cout << "Array A: " << massA << " (size: " << massA.size() << ")\n";
    cout << "Array D: " << massD << " (size: " << massD.size() << ")\n";
    // Слияние (объединение) двух массивов в один
    cout << "Merge (" << massC << " and " << massD << ") = " << massC.merge(massD) << endl;
    cout << "Merge (" << massC.merge(massD) << " and " << massC.merge(massD) << ") = "
         << massC.merge(massD).merge(massC.merge(massD)) << endl;
    // Очистка массива
    massC.clear();
    // Добавление элементов в конец массива
    cout << "Array C (before add): " << massC << " (size: " << massC.size() << ")\n";
    for (size_t i = 0; i < 100; ++i) { massC.push_back(i); }
    // Удаление элементов из массива (idx, count)
    cout << "Array C (after add): " << massC << " (size: " << massC.size() << ")\n";
    massC.erase(5, 95);
    cout << "Array C (after erase): " << massC << " (size: " << massC.size() << ")\n";
    massC.erase(0, 5);
    cout << "Array C (after erase): " << massC << " (size: " << massC.size() << ")\n";
    // Произведение элементов массива
    for (size_t i = 1; i <= 5; ++i) { massC.push_back(i); }
    cout << "Array C: " << massC << " [mul(Array C): " << massC.mul() << "]\n";
    cout << "Array C: " << massC << " [mul(Array C) * 6: " << massC.mul(6) << "]\n";
    // Определение максимального и минимального элементов
    cout << "Array C: " << massC << " [max(Array C): " << massC.max() << "]\n";
    cout << "Array C: " << massC << " [min(Array C): " << massC.min() << "]\n";
    // Умножение и деление элементов массива
    cout << "Array C: " << massC << " [(Array C * 5) / 4: " << ( massC * 5 ) / 4 << "]\n";
    // Вставка одного массива в заданную позицию другого
    for (size_t i = 0; i <= massC.size(); ++i) {
        cout << "Array C in Array C (" << i << "): " << massC.insert(massC, i) << endl;
    }
}