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

Int main ()

{

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

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

// Выделяем достаточно большой блок памяти

int * pData =new int[ 50 ];

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

int numbersCount = 0;

while (true )

{

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

int temp;

std::cin >> temp;

// В случае успеха записываем число в массив, увеличивая счетчик

if ( std::cin )

pData[ numbersCount++ ] = temp;

else

// Иначе прерываем ввод

break;

}

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

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

for (int i = numbersCount - 1; i >= 0; i-- )

std::cout << pData[ i ] << ' ';

std::cout << std::endl;

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

delete[]pData;

}

Программа будет прекрасно справляться с поставленной задачей до тех пор, пока количество вводимых чисел не превысит 50. Если же пользователь введет больше чисел, например, 51, программа будет завершиться с крахом, поскольку произойдет запись за дозволенные границы выделенного массива (скорее всего, крах будет обнаружен в момент выполнения освобождения памяти инструкцией delete[]):

Очевидно, такое поведение является неприемлемым. Наивное решение состоит в увеличении размера выделяемой памяти. Но на любое подобное допущение всегда найдется набор входных данных, который разрушит программу. Еще одна наивная мысль - выделить огромное количество ячеек, скажем миллион, что скорее всего хватит для практически любых случаев, которые реально могут встретиться. Огромный недостаток этой очередной идеи состоит в крайне нерациональном расходовании ресурсов памяти. Несколько подобных приемов - и никакого объема оперативной памяти на компьютере не хватит.

В результате данного рассуждения остается лишь прийти к следующим выводам:

  1. Программа должна обрабатывать количество данных, которое в нее вводит пользователь.

  2. Программа не должна завершаться фатально ни при каком вводе.

  3. Программа должна рационально расходовать память, выделяя необходимый ей минимум.

Каким же образом можно удовлетворить вышеуказанным требованиям к реализации?

Динамически растущие массивы (векторы)

Применим простейшую классическую структуру данных - динамически растущий массив. Во многих языках программирования эту структуру также называют вектором.

Основная идея такого массива состоит в резервировании некоторого небольшого объема памяти для данных и последующем автоматическом расширении как только текущий объем полностью заполняется. Для организации такой структуры необходимо ввести 3 переменные:

  • адрес начала текущего блока памяти для хранения (pData);

  • число выделенных ячеек в текущем блоке памяти (nAllocated);

  • число фактически занятых полезными данными ячеек в данный момент (nUsed).

Начальный выделяемый объем может быть произволен, разумной начальной настройкой является 8-10 ячеек. В начале часть выделенных ячеек использоваться не будет. Ячейки будут заполняться данными по мере ввода:

Затем, как только число занятых ячеек сравняется с числом выделенных, массив следует расширить вдвое. Прямого способа расширить выделенный массив язык С++ не предоставляет. Поэтому под расширением понимают выделение нового большего блока данных, перенос ранее введенных данных и освобождение старого блока. После расширения новый блок будет заполнен на 50%, а значит сможет принять еще столько же входных данных:

Продемонстрируем данную идею модифицировав часть предыдущей версии программы:

#include<iostream>

#include<cstring>

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