Хранение данных

Предположим, что вы разработали компьютерную игру под названием "Враждебный пользователь", в которой игроки состязаются с замысловатым и недружественным компьютерным интерфейсом. Теперь вам необходимо написать программу, которая отслеживает ежемесячные объемы продаж этой игры в течение пятилетнего периода. Или, скажем, вам нужно провести инвентаризацию торговых карт героев-хакеров.
Очень скоро вы придете к выводу, что для накопления и обработки информации вам требуется нечто большее, чем простые базовые типы данных.
 

Массивы (списки). Введение

Для того чтобы было удобно работать с большим количеством данных, группе ячеек дают общее имя. Такую группу ячеек называют массивом
Массив – это группа ячеек памяти одинакового типа, расположенных рядом и имеющих общее имя. Каждая ячейка в группе имеет уникальный номер.

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


Массивы в языке Pascal


Традиционно в языке Паскаль используются статические массивы вида

var a: array [1..10] of integer;

Границы массива обязательно задаются константами, и изменить размер массива в ходе работы программы нельзя. Зато можно сделать индекс не только целого, но и, скажем, символьного или перечислимого типа. Например, для подсчета встречаемости каждой буквы можно использовать массив

var LettersCount: array ['a'..'z'] of integer;

и работать с ним в свое удовольствие:

LettersCount['z'] := 1;
LettersCount['d'] := LettersCount['d'] + 1;

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

Создание массива

При создании массива в памяти выделяется место (определенное число ячеек)
1) Массивы можно создать простым перечислением элементов:
var a: array of integer;
SetLength(a, 3);
a[0] := 1;
a[1] := 2;
a[2] := 3;

2) Массивы можно составить из данных любых типов - целых или вещественных чисел, символьных строк 
var a: array of char;
SetLength(a, 3);
a[0] := 'a';
a[1] := 'b';
a[2] := 'c';
3) Массив всегда "знает" свой размер. Для определения размера массива используется функция length. Часто размер массива хранят в отдельной переменной, чтобы была возможность легко изменить программу для работы с другим размером массива. Пример:
N := 10;         //в переменной N храним размер массива
SetLength(a, N);  // устанавливаем массиву а размер N  
writeln(length(a));  //выводим размер массива
Размер массива можно задавать с клавиатуры.

Обращение к элементу массива

Большая часть пользы от массивов определяется тем фактом, что к его элементам можно обращаться индивидуально.
Способ, который позволяет это делать, заключается в использовании индекса для нумерации элементов.
Индекс - это значение, которое указывает на конкретный элемент массива

ЗАПОМНИТЕ!
НУМЕРАЦИЯ МАССИВОВ В PASCAL НАЧИНАЕТСЯ С НУЛЯ!

(Это является обязательным — вы должны начинать с нуля. Это особенно важно запомнить)

Примеры обращения к массиву A:
x := (A[3] + 5) * A[1] // прочитать значения A[3] и A[1]
A[0] := x + 6        // записать новое значение в A[0]
Разберем программу работы с элементами массива.
var i: integer;
a: array of integer;

begin
    i := 1;
    setlength(a, 5); //создаем массив из 5 элементов 
    a[0] := 23; // в каждый из 5 элементов массива (индексы от 0 до 4)
    a[1] := 12; // записываем определенное значение
    a[2] := 7;
    a[3] := 43;
    a[4] := 51;
    a[2] := a[i] + 2 * a[i - 1] + a[2 * i]; // изменим значение элемента с индексом 2, на результат выражения
    // т.к i=1, то подставляя значение переменной i в выражение получим
    // следующее выражение  a[2] := a[1] + 2*a[0] + a[2];
    writeln(a[2] + a[4]);
end.


В результате выполнения данной программы на экране появится значение суммы элементов массива с индексом 2 и с индексом 4 равное 116. Как видно из примера, мы можем обращаться к любому элементу массива. А также вычислять необходимый номер элемента по различным формулам (например, как в программе A[i-1] или A[2*i], в данных случаях индексы элементов будут вычислены и зависят от значения i.)

Разберем пример программы
var a: array of integer;

begin
    setlength(a, 5);
    a[5] := 5;
    a[-1] := 0;
end.

Т.к. массив объявлен из 5 элементов, значит элементы будут иметь нумерацию от 0 до 4. Видим, что программа в 6й строке обращается к несуществующему элементу а[5] и в 7ой строке к также несуществующему а[-1].

Получается, что программа вышла за границы массива
Выход за границы массива - это обращение к элементу с индексом, который не существует в массиве.
В таких случая программа обычно завершается аварийно с ошибкой run-time error


 
 

При работе с массивами обычно приходится работать сразу со всеми элементами массива.
Перебор элементов: просматриваем все элементы массива и, если нужно, выполняем с каждым из них некоторую операцию.
Для этого используется чаще всего цикл с переменной, которая изменяется от 0 до N-1, где N количество элементом массива.
Под N будем считать текущий размер массива, то есть
N := length(A)
...
for i := 0 to n - 1 do begin
     // здесь работаем с a[i]
end;
...
В указанном цикле переменная i будет принимать значения 0, 1, 2, ...,N-1.  Таким образом, на каждом шаге цикла мы обращаемся к конкретному элементу массива с номером i.
Таким образом, достаточно описать, что нужно сделать с одним элементом массива a[i] и эти действия поместить внутрь такого цикла.

Напишем программу, которая заполняет массив первыми N натуральными числами, то есть по окончании программы элементы массива должны стать равными
a[0] = 1
a[1] = 2
a[2] = 3
...
a[N - 1] = N
Нетрудно заметить закономерность: значение элемента массива должно быть больше на 1, чем индекс элемента.
Цикл будет выглядеть следующим образом
for i := 1 to n - 1 do
    a[i] := i + 1; 

Выполните задание.