Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СТА (лекции+лабы) / СТА Лекция 1.docx
Скачиваний:
54
Добавлен:
16.03.2016
Размер:
336.41 Кб
Скачать

Struct IntegerVector

{

Int * m_pData;

Int m_nUsed;

Int m_nAllocated;

};

Следует отметить, что все переменные, входящие в состав структуры получили префикс “m_”, что означает членство (membership). Это не является обязательным требованием языка С++, а всего лишь рекомендуемой многими профессиональными программистами стилистической конвенцией. Такие идентификаторы легко отличить от других видов переменных благодаря префиксу, что повышает читабельность кода.

Типичные манипуляции со структурой-вектором следует выделить в отдельные функции с интуитивно понятным интерфейсом. Во-первых, необходима функция инициализации вектора, т.е., приведения его в начальное пригодное к использованию состояние:

void IntegerVectorInit ( IntegerVector & _vector,int _allocatedSize = 10 )

{

_vector.m_pData =new int[ _allocatedSize ];

_vector.m_nAllocated = _allocatedSize;

_vector.m_nUsed = 0;

}

Во-вторых, вектор должен освобождать выделенные им ресурсы памяти:

Void IntegerVectorDestroy ( IntegerVector & _vector )

{

delete[]_vector.m_pData;

}

В-третьих, необходима функция для добавления очередного числа в конец вектора, которая автоматически увеличивает размер вектора в случае необходимости:

void IntegerVectorPushBack ( IntegerVector & _vector,int _data )

{

// Закончилось ли место в векторе?

if ( _vector.m_nUsed == _vector.m_nAllocated )

{

// Выделяем новый блок, в 2 раза больше прежнего

int nAllocatedNew = _vector.m_nAllocated * 2;

int * pNewData =new int[ nAllocatedNew ];

// Копируем данные из прежнего блока в новый

memcpy(

pNewData,

_vector.m_pData,

sizeof(int ) * _vector.m_nAllocated

);

// Освобождаем старый блок и подменяем адрес на новый блок

delete[]_vector.m_pData;

_vector.m_pData = pNewData;

// Обновляем количество выделенных ячеек

_vector.m_nAllocated = nAllocatedNew;

}

// Записываем данное в очередную ячейку

_vector.m_pData[ _vector.m_nUsed++ ] = _data;

}

Аргументы функций получили префикс в виде символа “_”, что также является одной из популярных стилистических конвенций.

Имея под рукой такие вспомогательные функции, выделенные из предыдущей версии программы, преобразуем основную программу в простую и очень читабельную:

int main ()

{

// Приглашение пользователя ко вводу

std::cout << "Input integers, stop with Ctrl+Z: ";

// Создаем вектор и инициализируем его одним вызовом

IntegerVector v;

IntegerVectorInit( v );

// Пытаемся вводить числа с консоли одно за другим

while (true )

{

// Попытка ввода числа

int temp;

std::cin >> temp;

if ( std::cin )

// Просто просим вектор добавить новое данное в конец

IntegerVectorPushBack( v, temp );

else

// Конец ввода

break;

}

// Количество введенных данных сохранено в переменной m_nUsed в векторе

// Выводим данные в обратном порядке

for (int i = v.m_nUsed - 1; i >= 0; i-- )

std::cout << v.m_pData[ i ] << ' ';

std::cout << std::endl;

// Просим вектор освободить выделенные им ресурсы

IntegerVectorDestroy( v );

}

Как видим, все сложные манипуляции со структурой данных были полностью скрыты внутри обеспечивающих функций, а тело функции main теперь сосредоточено на решении задачи.

Повторное использование решения

Предположим, возникла более сложная задача. Пользователь вводит последовательность целых чисел произвольной длины, программа создает последовательность частичных сумм и выводит ее на экран. Если на вход подана последовательность “1 2 3 4 5”, программа должна выдавать последовательность “1 3 6 10 15”, где каждое следующее число формируется как сумма текущего числа и всех предыдущих обработанных.

Чтобы не реализовывать логику работы с динамически растущим массивом целых чисел снова и снова, сначала следует применить еще один этап рефакторинга, выделив логику структуры данных в отдельные файлы исходного кода. Следует сформировать заголовочный файл с описанием структуры и прототипами функций, а тела функций разместить в отдельный файл. Заголовочный файл следует включать во всех местах использования данной функциональности.

integer_vector.hpp

Соседние файлы в папке СТА (лекции+лабы)