Вы находитесь на странице: 1из 5

Array.

h
#ifndef ArrayH
#define ArrayH
//---------------------------------------------------------------------------
#include <assert.h>
#include "Algo.h"
//---------------------------------------------------------------------------
/*
Шаблон класса: одномерный динамический массив из элементов типа T.
*/
template <class T>
class Array {

private:
unsigned FCount; // число элементов
T* FData; // указатель на первый элемент массива (если
FCount > 0)

public:
// Создание массива из count элементов, по умолчанию 0.
Array(unsigned count = 0)
: FCount(0) // инициализируем элемент FCount конструктором
копии
{ // (вместо конструктора по
умолчанию)
Resize(count, false);
}

// Создание массива из count элементов, которые инициализируются


// count элементами, на которые указывает data.
Array(unsigned count, const T *data)
: FCount(0)
{
Assign(count, data);
}

// Конструктор копии.
Array(const Array& array)
: FCount(0)
{
Assign(array.FCount, array.FData);
}

// Деструктор (освобождает память).


~Array()
{
Clear();
}

// Возвращает размер массива.


unsigned Count() const { return FCount; }
// Задает размер массива.
void Count(unsigned count) { Resize(count); }

// Устанавливает размер массива в count и копирует в него count элементов


// data[0], data[1], ..., data[count - 1].
void Assign(unsigned count, const T *data);

// Устанавливает размер массива. Старые элементы (сколько влезут в новый


размер)
// по умолчанию остаются (параметр store = true), либо теряются (store =
false).
void Resize(unsigned count, bool store = true);

// Удаление всех элементов.


void Clear()
{
Count(0);
}

// Операция присваивания. Устанавливается такой же размер и копируются данные


из array.
Array& operator =(const Array& array)
{
// Если не имеет место самоприсваивание (Array<T> a; a = a;), то
if (this != &array)
// выполняем присваивание.
Assign(array.FCount, array.FData);
// Возвращаем ссылку на левый аргумент операции присваивания, чтобы позволить,
например,
// дальнейшее присваивание (Array<T> a, b, c; a = b = c;).
return *this;
}

// Операция индексации (для константного массива).


const T& operator [](unsigned index) const
{
assert(index < FCount); // проверка корректности индекса
return FData[index]; // и возврат константной ссылки на элемент
}

// Операция индексации (для неконстантного массива).


T& operator [](unsigned index)
{
assert(index < FCount); // проверка корректности индекса
return FData[index]; // и возврат ссылки на элемент
}

// Операция вывода в поток.


friend ostream& operator <<(ostream &stream, const Array& array)
{
// Вывод в поток и
Write(array.FData, array.FCount, stream);
// возврат ссылки на поток, чтобы позволить последующий вывод (нап: cout << a
<< b).
return stream;
}

// Операция ввода из потока.


friend istream& operator >>(istream &stream, Array& array)
{
// Ввод из потока и
Read(array.FData, array.FCount, stream);
// возврат ссылки на поток, чтобы позволить последующий ввод (нап: cin >> a >>
b).
return stream;
}

// Операция равенства.
friend bool operator ==(const Array& x, const Array& y)
{
// Если массивы являются различными объектами, то выполняем сравнение.
if (&x != &y)
// Если число элементов одинаково,
if (x.FCount == y.FCount)
// то выполняем поэлементное сравнение.
return Compare(x.FData, y.FData, FCount);
// Иначе, массивы не равны.
else
return false;
// Иначе возвращаем истину (т. к. любой массив сам себе равен).
return true;
}

// Операция неравенства.
friend bool operator !=(const Array& x, const Array& y)
{
return !(x == y);
}

};
//---------------------------------------------------------------------------
// Определение не встраиваемых функций-элементов
//---------------------------------------------------------------------------
template <class T>
void Array<T>::Assign(unsigned count, const T *data)
{
Resize(count, false); // устанавливаем размер, без сохранения элементов
Copy(FData, data, FCount); // и копируем данные
}
//---------------------------------------------------------------------------
template <class T>
void Array<T>::Resize(unsigned count, bool store)
{
// Если число элементов изменяется.
if (FCount != count) {
// Если новое число элементов не нулевое, то распределяем память;
if (count) {
// Создаем динамический массив из count элементов,
T *p = new T[count];
// и копируем туда старые элементы (сколько влезет), если требуется.
if (store)
Copy(p, FData, Min(FCount, count));
// Уничтожаем старый массив, если он не пуст.
if (FCount) delete[] FData;
// Сохраняем в классе адрес первого элемента нового массива.
FData = p;
}
// иначе освобождаем память.
else
delete[] FData;
// Сохраняем новое число элементов в классе.
FCount = count;
}
}
//---------------------------------------------------------------------------
#endif

Ex_Array.cpp

#include <fstream.h>
#include "Array.h"

// Вспомогательный класс для вывода массива в поток.


template <class T>
class Wr {
const char *Name; // имя массива
const Array<T> &Arr; // ссылка на массив

public:
Wr(const char *n, const Array<T> &a) : Name(n), Arr(a) { }
friend ostream& operator <<(ostream &s, const Wr<T> &w)
{
// Выводим имя массива, знак равенства, элементы и конец строки.
s << w.Name << " = " << w.Arr << endl; return s;
}

};

// Тип элемента.
typedef int Type;
// Чтобы все время не указывать параметры шаблона, обычно используют синоним
типа.
typedef Array<Type> TypeArray;
typedef Wr<Type> W;

const unsigned SZ = 5;
const Type Init[5] = { 1, 2, 3, 4, 5 };

void main()
{
// Создадим массивы, используя все доступные конструкторы,
TypeArray a, // пустой массив
b(3), // массив из 3 эл-в, создаваемых к-ром по умолчанию
// (для int к-р по умолчанию определен
компилятором, который
// ничего не делает, т. е. значение не определено)
c(SZ, Init), // массив из SZ эл-в с инициализацией
d(c); // к-р копии
// создадим вспомогательные классы вывода, и
W wa("a", a), wb("b", b), wc("c", c), wd("d", d);
// посмотрим результат.
cout << wa << wb << wc << wd << endl;

// Удвоим число элементов в массиве c без сохранения эл-в.


c.Resize(c.Count() * 2, false); cout << wc;
// Заполним массив c, используя эл-ты из d,
unsigned i;
for (i = 0; i < d.Count(); i++) {
c[i * 2] = d[i];
c[i * 2 + 1] = 2 * d[i];
}
// и скопируем в a.
a = c;
cout << wc << wa << endl;

// Удвоим число элементов в массиве d,


d.Count(d.Count() * 2); cout << wd;
// и скопируем новые эл-ты из c.
for (i = d.Count() / 2; i < d.Count(); i++)
d[i] = c[i];
cout << wd << endl;

// Протестируем операци равенства.


cout << "a == b: " << (a == b) << endl;
cout << "a == c: " << (a == c) << endl;
cout << "a == d: " << (a == d) << endl;
cout << "a != b: " << (a != b) << endl;
cout << "a != c: " << (a != c) << endl;
cout << "a != d: " << (a != d) << endl;

// Теперь сделаем массив из вспомогательных классов вывода, и


// выведем все массивы в файл "_out.txt" при помощи функции Write.
{
W x[] = {wa, wb, wc, wd};
ofstream f("_out.txt");
Write(x, 4, f, "-------------------------\n");
}

cin.ignore(100, 'q');
}