Понятие массива в программировании. Работа с массивами данных.Одномерные и двумерные массивы. Какие действия производятся с элементами массива

До сих пор мы работали с простыми типами данных – логический (boolean), целый (integer , word , byte , longint), вещественный (real), символьный (char). Любой алгоритм можно запрограммировать с помощью этих четырех базовых типов. Но для обработки информации о многообразном реальном мире требуются данные, имеющие более сложное строение. Такие сложные конструкции, основанные на простейших скалярных типах, называются структурами. Структура – некоторый составной тип данных, составленный из базовых скалярных. Если структура не изменяет своего строения на протяжении всего выполнения программы, в которой она описана, то такую структуру называют статической.

Массив – однородная совокупность элементов

Самой распространенной структурой, реализованной практически во всех языках программирования, является массив.

Массивы состоят из ограниченного числа компонент, причем все компоненты массива имеют один и тот же тип, называемый базовым. Структура массива всегда однородна. Массив может состоять из элементов типа integer , real или char , либо других однотипных элементов. Из этого, правда, не следует делать вывод, что компоненты массива могут иметь только скалярный тип.

Другая особенность массива состоит в том, что к любой его компоненте можно обращаться произвольным образом. Что это значит? Программа может сразу получить нужный ей элемент по его порядковому номеру (индексу).

Индекс массива

Номер элемента массива называется индексом . Индекс – это значение порядкового типа, определенного, как тип индекса данного массива. Очень часто это целочисленный тип (integer , word или byte), но может быть и логический и символьный.

Описание массива в Паскале. В языке Паскаль тип массива задается с использованием специального слова array (англ. – массив), и его объявление в программе выглядит следующим образом:

Type < имя _ типа >= array [ I ] of T;

где I – тип индекса массива, T – тип его элементов.

Можно описывать сразу переменные типа массив, т.е. в разделе описания переменных:

Var a,b: array [ I ] of T;

Обычно тип индекса характеризуется некоторым диапазоном значений любого порядкового типа: I 1 .. I n . Например, индексы могут изменяться в диапазоне 1..20 или " a ".." n ".

При этом длину массива Паскаля характеризует выражение:

ord (I n)- ord (I 1)+1.

Вот, например, объявление двух типов: vector в виде массива Паскаля из 10 целых чисел и stroka в виде массива из 256 символов:

Type
Vector=array of integer;
Stroka=array of char;

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

Опишем переменные типа vector и stroka:

Вычисление индекса массива Паскаля

Индекс массива в Паскале не обязательно задавать в явном виде. В качестве индекса массива можно использовать переменную или выражение, соответствующее индексному типу. Иначе говоря, индексы можно вычислять.

Этот механизм – весьма мощное средство программирования. Но он порождает распространенную ошибку: результат вычислений может оказаться за пределами интервала допустимых значений индекса, то есть будет произведена попытка обратиться к элементу, которого не существует. Эта типичная ошибка называется «выход за пределы массива».

Пример программы с ошибкой массива Паскаля

Program primer _ error ;
Type
vector=array of word;
var
n: integer;
a: vector;
begin
n:=45;
a:=25;
end .

Хотя данная программа полностью соответствует синтаксису языка, и транслятор «пропустит» ее, на стадии выполнения произойдет ошибка выхода за пределы массива Паскаля. При n =45 выражение n *2=90, компьютер сделает попытку обратиться к элементу массива a , но такого элемента нет, поскольку описан массив размерностью 80.

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

Из всего этого следует сделать вывод: программисту надо быть очень аккуратным при работе с индексами массива.

Основные действия с массивами Паскаля

Как известно, определение типа данных означает ограничение области допустимых значений, внутреннее представление в ЭВМ, а также набор допустимых операций над данными этого типа. Мы определили тип данных как массив Паскаля. Какие же операции определены над этим типом данных? Единственное действие, которое можно выполнять над массивами целиком, причем только при условии, что массивы однотипны, – это присваивание. Если в программе описаны две переменные одного типа, например,

Var
a , b: array of real ;

то можно переменной a присвоить значение переменной b (a:= b). При этом каждому элементу массива a будет присвоено соответствующее значение из массива b . Все остальные действия над массивами Паскаля производятся поэлементно (это важно!) .

Ввод массива Паскаля

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

Пример фрагмента программы ввода массива Паскаля

Var
A: array of integer ;
Begin
For i:=1 to 10 do
Readln (a[i]); { ввод i- го элемента производится с клавиатуры }

Рассмотрим теперь случай, когда массив Паскаля заполняется автоматически случайными числами, для этого будем использовать функцию random (N).

Пример фрагмента программы заполнения массива Паскаля случайными числами

Var
I: byte ; {переменная I вводится как индекс массива}
Begin
For i:=1 to 10 do
A [ i ]:= random (10); { i -му элементу массива присваивается «случайное» целое число в диапазоне от 0 до 10}

Вывод массива Паскаля

Вывод массива в Паскале осуществляется также поэлементно, в цикле, где параметром выступает индекс массива, принимая последовательно все значения от первого до последнего.

Пример фрагмента программы вывода массива Паскаля

Var
A: array of integer;
I: byte ; {переменная I вводится как индекс массива}
Begin
For i:=1 to 10 do
Write (a [ i ]," "); {вывод массива осуществляется в строку, после каждого элемента печатается пробел}

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

Пример программы вывода массива Паскаля в столбик

Var
A: array of integer;
I: byte ; {переменная I вводится как индекс массива}
Begin
For i:=1 to 10 do
Writeln ("a[", i,"]=", a[i]); { вывод элементов массива в столбик }

На экране мы увидим, к примеру, следующие значения:

a =2
a =4
a =1 и т.д.

Пример решения задачи с использованием массивов Паскаля

Задача: даны два n -мерных вектора. Найти сумму этих векторов.

Решение задачи:

  • Входными данными в этой задаче будут являться два одномерных массива. Размер этих массивов может быть произвольным, но определенным. Т.е. мы можем описать заведомо большой массив, а в программе определить, сколько элементов реально будет использоваться. Элементы этих массивов могут быть целочисленными. Тогда описание будет выглядеть следующим образом:

    var a , b: array of integer ;

  • Выходными данными будут элементы результирующего массива, назовем его c . Тип результирующего массива также должен быть целочисленным.
  • Кроме трех массивов нам потребуется переменная – параметр цикла и индекс массива, назовем ее i , а также переменная n для определения количества элементов в каждом массиве.

Ход решения задачи:

  • определим количество элементов (размерность) массивов, введем значение n ;
  • введем массив a ;
  • введем массив b ;
  • в цикле, перебирая значения индекса i от 1 до n , вычислим последовательно значения элементов массива c по формуле:

    c [ i ]= a [ i ]+ b [ i ];

  • выведем на экран полученный массив.

Текст программы:

Пример программы суммирования векторов

Program summa;
Var
a, b, c: array of integer;
I, n: byte;
Begin
Write ("введите размерность массивов:");
Readln(n);
For i:=1 to n do
Readln (a[i]); { ввод массива a}
For i:=1 to n do
Readln (b[i]); { ввод массива b}
For i:=1 to n do
C[i]:=a[i]+b[i]; { вычисление суммы массивов }
For i:=1 to n do
write (c[i]," "); { вывод массива с }
end.

Массив

Размерность массива - количество индексов, необходимое для однозначного доступа к элементу массива .

Форма или структура массива - количество размерностей и размер (протяжённость) массива для каждой размерности , может быть представлен одномерным массивом .

В ряде языков программирования, например, Лисп , JavaScript , PHP , Ruby применяются также ассоциативные массивы (или хэш-массивы), в которых элементы не обязательно являются однотипными, а доступ к ним не обязательно осуществляется по индексу.

Общее описание

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

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

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

{Одномерный массив целых чисел. Нумерация элементов от 1 до 15} a: array [ 1 .. 15 ] of Integer ; {Двумерный массив символов. Нумерация по столбцам по типу Byte (от 0 до 255) по строкам от 1 до 5} multiArray : array [ Byte , 1 .. 5 ] of Char ; {Одномерный массив из строк. Нумерация по типу word (от 0 до 65536)} rangeArray : array [ Word ] of String ;

Пример статического массива на С/С++

Int Array[ 10 ] ; // Одномерный массив целых чисел размера 10 // Нумерация элементов от 0 до 9 double Array[ 12 ] [ 15 ] ; // Двумерный массив вещественных чисел двойной точности // размера 12 на 15. // Нумерация по столбцам от 0 то 11, по строкам от 0 до 14

Поддержка индексных массивов (свой синтаксис объявления, функции для работы с элементами и т. д.) есть в большинстве высокоуровневых языков программирования . Максимально допустимая размерность массива, типы и диапазоны значений индексов, ограничения на типы элементов определяются языком программирования и/или конкретным транслятором.

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

Объявление типа «массив» в языке Паскаль

Type TArrayType = array [ 0 .. 9 ] of Integer ; (* Объявления типа "массив" *) var arr1, arr2, arr3: TArrayType; (* Объявление трёх переменных-массивов одного типа *)

Специфические типы массивов

Динамические массивы

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

Пример динамического массива на Delphi

ByteArray : Array of Byte ; // Одномерный массив multiArray : Array of Array of string ; // Многомерный массив

Пример динамического массива на Си

Float * array1; // Одномерный массив int ** array2; // Двумерный массив array1 = (float * ) malloc (10 * sizeof (float ) ) ; // выделение 10 блоков по sizeof(float) байт каждый array2 = (int ** ) malloc (16 * sizeof (int * ) ) ; // выделение 16 блоков по sizeof(int*) байт каждый. Сюда будут записаны указатели на одномерные массивы-строки for (i = 0 ; i < 16 ; i++ ) array2[ i] = (int * ) malloc (8 * sizeof (int ) ) ; // выделение 8 блоков по sizeof(int) байт каждый. Это одномерные массивы - строки матрицы. // Обращение к массиву array1[ i] = 5.0 ; * (array1+ i) = 5.0 ; array2[ i] [ j] = 6 ; // Записи эквивалентны. Первая с использованием индекса, * (* (array2+ i) + j) = 6 ; // вторая с операцией разыменования.

Пример динамического массива на С++

Float * array1; // Одномерный массив int ** array2; // Многомерный массив array1 = new float [ 10 ] ; // выделение 10 блоков размером типа float array2 = new int * [ 16 ] ; // выделение 16 блоков размером типа указателя на int for (int i = 0 ; i < 16 ; i++ ) { array2[ i] = new int [ 8 ] ; }

Гетерогенные массивы

Гетерогенным называется массив, в разные элементы которого могут быть непосредственно записаны значения, относящиеся к различным типам данных . Массив, хранящий указатели на значения различных типов, не является гетерогенным, так как собственно хранящиеся в массиве данные относятся к единственному типу - типу «указатель». Гетерогенные массивы удобны как универсальная структура для хранения наборов данных произвольных типов. Отсутствие их поддержки в языке программирования приводит к необходимости реализации более сложных схем хранения данных. С другой стороны, реализация гетерогенности требует усложнения механизма поддержки массивов в трансляторе языка. Гетерогенный массив как встроенный тип данных присутствует в языках PHP и 1С .

Реализация

Одним из способом реализации статических массивов с одним типом элементов является следующий (в Фортране порядок индексов противоположен таковому в Си ):

  1. Под массив выделяется непрерывный блок памяти объёмом S*m 1 *m 2 *m 3 …m n , где S - размер одного элемента, а m 1 …m n - размеры диапазонов индексов (то есть количество значений, которые может принимать соответствующий индекс).
  2. При обращении к элементу массива A адрес соответствующего элемента вычисляется как B+S*((…(i 1p *m 1 +i 2p)*m 2 +…+i (n-1)p)*m n-1 +i np), где B - база (адрес начала блока памяти массива), i kp - значение k-го индекса, приведённое к целому с нулевым начальным смещением.

Таким образом, адрес элемента с заданным набором индексов вычисляется так, что время доступа ко всем элементам массива одинаково.

Первый элемент массива, в зависимости от языка программирования , может иметь различный индекс. Различают три основных разновидности массивов: с отсчетом от нуля (zero-based), с отсчетом от единицы (one-based) и с отсчетом от специфического значения заданного программистом (n-based). Отсчет индекса элемента массивов с нуля более характерен для низкоуровневых языков программирования , однако этот метод был использован в языках более высокого уровня языком программирования Си.

Более сложные типы массивов - динамические и гетерогенные - реализуются сложнее.

Достоинства

  • лёгкость вычисления адреса элемента по его индексу (поскольку элементы массива располагаются один за другим)
  • одинаковое время доступа ко всем элементам
  • малый размер элементов: они состоят только из информационного поля

Недостатки

  • для статического массива - отсутствие динамики, невозможность удаления или добавления элемента без сдвига других
  • для динамического и/или гетерогенного массива - более низкое (по сравнению с обычным статическим) быстродействие и дополнительные накладные расходы на поддержку динамических свойств и/или гетерогенности.
  • при работе с массивом в стиле C (с указателями) и при отсутствии дополнительных средств контроля - угроза выхода за границы массива и повреждения данных

См. также

Литература

  • Вирт Н. Алгоритмы и структуры данных = Algoritms and data structure. - М .: Мир, 1989. - 360 с. - ISBN 5-03-001045-9
  • Хювёнен Э., Сеппянен Й. Мир Лиспа. Введение в язык ЛИСП и функциональное программирование. В 2-х т. = Lisp-maailma: Johdatus kieleen ja ohjelmointiin / Пер. с финск. - М .: Мир, 1990. - ISBN 5-03-001935-9
  • Магариу Н. А. Язык программирования АПЛ. - М .: «Радио и связь», 1983. - 96 с.
  • Бартеньев О. В. Современный Фортран. - 3-е изд., доп. и перераб.. - М .: ДИАЛОГ-МИФИ, 2000. - 449 с.

Примечания

Массив - это сложный (составной, структурированный) тип данных, который характеризуется следующим:

· элементы массива имеют одинаковый тип в отличие от структур, поэтому каждый элемент массива занимает одинаковый объём памяти;

· массив располагается в оперативной памяти, а не на внешнем устройстве, как файлы (2-й семестр);

· элементы массива занимают подряд идущие ячейки, в отличие, например, от списков (2-й семестр).

Доступ к элементам массива в языке С++ осуществляется двумя способами.

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

Кроме того, в языке С++ есть возможность обрабатывать массивы, используя указатели (адреса) , так как в С++ существует связь между массивами и указателями. Несмотря на то, что в первом способе в программе отсутствует специальный тип для работы с адресами, указатели всё равно используются.

Массивы могут иметь одну или несколько размерностей. В этом параграфе рассматривается одномерный массив, который иногда называют вектором , подразумевая вектор в n -мерном пространстве. Работа с двумерными массивами (матрицами ) рассматривается в гл. 5. Три и более размерностей на практике используются редко, так как такие массивы занимают большой объём оперативной памяти.

Везде в дальнейшем под словом “массив” будем понимать одномерный массив.

С точки зрения времени (этапа), когда распределяется память под массив, существуют два их вида. Память для динамического массива выделяется во время выполнения программы, и если массив не нужен, память для него можно освободить. Такие массивы рассматриваются во втором семестре.

Одномерный массив с фиксированной размерностью (назовём его статический ) объявляется в общем виде следующим образом:

тип имя [N];

Здесь тип - тип элементов массива. Вначале будем рассматривать простые типы (int, float, char ), но можно использовать и сложные, например, структуры. Имя записывается по правилам идентификаторов. Каждый элемент массива имеет одно и то же имя, меняется только индекс или номер элемента. N - размерность (или размер) массива в виде целочисленной константы или константного выражения. Эта величина определяет количество ячеек оперативной памяти, зарезервированной для массива. Например:

float A; или const n=10; float A[n];

Преимущество второго способа c предварительным объявлением размерности в виде константы заключается в следующем. Если надо будет изменить размерность массива, то это достаточно сделать в одном месте программы при определении константы.

В отличие от динамического массива, для статического на этапе компиляции резервируется память для размещения N чисел указанного типа (10 вещественных чисел). Для массива требуется память объёмом k*N байт (4*10 ), где k - необходимое количество байт для размещения одного элемента указанного типа (одного числа типа float ). Эта память сохраняется на всё время выполнения программы, а точнее, функции или блока, где описан массив. Программно необходимый объём памяти определяется с помощью операции sizeof следующим образом:

M=sizeof (тип)*N ; или M= sizeof (имя) ; или M= sizeof имя ;

где M - переменная целого типа, определяющая размер массива в байтах. Тип обязательно записывается в скобках, а имя может быть без скобок. Следующая программа выведет дважды число 40.

float A; int M1, M2;

M1=sizeof(float)*10; // но M1=sizeof float *10;- ошибка!

M2=sizeof(A); // или M2=sizeof A;

cout<

Во многих современных системах программирования, в том числе и в С++, нумерация элементов массива начинается с 0. Тогда A - последний элемент массива. Это связано с использованием указателей при работе с массивами (см. 2-й семестр). Поэтому в нашем примере индекс изменяется от 0 до 9 включительно, то есть индекс последнего элемента массива на единицу меньше его размерности. Объявленные 10 элементов массива обозначаются следующим образом: A, A, A ,…, A . В С++ отсутствует проверка границ массивов. Можно выйти за его границу и записать значение в некоторую переменную или даже в код программы. О таком контроле должен позаботиться программист.

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

const nmax=100; float X;

int n; cout<<”Input the size of array ”; cin>>n;

/* Д альше работаем с n (а не с nmax ) элементами массива, например, вводим их.*/

for (int i=0; i

{ // Эту строку можно опустить вместе с фигурными скобками.

cout<<”X[“<

cin>>X[i];

Такой способ проще, но неэффективен с точки зрения распределения памяти, так как “заказываем” больше памяти, чем реально используем. В таких случаях профессионально используются более эффективные динамические массивы (см. 2-й семестр).

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

Объявление переменных массивового типа

Переменная массивового типа описывается в разделе описания переменных в следующей форме:

Var <идентификатор>: array[<тип индекса>] of <тип компонент>

Чаще всего в качестве типа индекса употребляется интервальный тип . Например, одномерный массив среднемесячных температур опишется так:

Var T: array of real;

Описание массива определяет, во-первых, размещение массива в памяти, во-вторых, правила его дальнейшего употребления в программе. Последовательные элементы массива располагаются в последовательных ячейках памяти (T, T и т.д.), причем значения индекса не должны выходить из диапазона 1...12. В качестве индекса может употребляться любое выражение соответствующего типа. Например:

T, T

Тип индекса может быть любым скалярным порядковым типом, кроме integer (в реализации Turbo Pascal). Например, в программе могут присутствовать следующие описания:

Var Cod: array of 1..100; L: array of Char;

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

Cod["x"]; L; cod; L;

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

Type Index=(А, В, С, D); Var Class_10: array of byte;

И если, например, элемент Class_10[A] равен 35, то это означает, что в 10 «А» классе 35 человек. Такое индексирование улучшает наглядность программы.

Часто структурированному типу присваивается имя в разделе типов, которое затем используется в разделе описания переменных.

Type Mas1 = array of integer; Mas2 = array[-10..10] of char; var Num: Mas1; Sim: Mas2;

Многомерные массивы

Многомерный массив в Паскале трактуется как одномерный массив, тип элементов которого также является массивом (массив массивов). Например, среднемесячную температуру за 10 лет можно можно хранить в массиве, описанном следующим образом:

Var H: array of array of real;

Вот примеры обозначения некоторых элементов этого массива:

Н; Н; Н;

Однако чаще употребляется другая, эквивалентная форма обозначения элементов двумерного массива:

Н; Н; Н;

Переменная Н обозначает всю первую строку таблицы, т.е. весь массив температур за 1981 г. Другим вариантом, эквивалентным приведенному выше описанию, является следующий:

Type Month = array of real; Year = array of Month; var H: Year;

Наиболее краткий вариант описания данного массива такой:

Var H: array of real;

Трехмерный массив можно определить как одномерный массив, у которого элементами являются двумерные массивы. Вот пример описания трехмерного массива:

Var A: array of integer;

Это массив, состоящий из 10x20x30 = 6000 целых чисел и занимающий в памяти 6000x2 = 12000 байт. В Паскале нет ограничения сверху на размерность массива. Однако в каждой конкретной реализации Паскаля ограничивается объем памяти, выделяемый под массивы.

По аналогии с математикой одномерные числовые массивы часто называют векторами, а двумерные - матрицами. Размер массивов не может быть изменен в процессе выполнения. Изменение размеров массива происходит через изменение в тексте программы и повторную компиляцию. Для упрощения таких изменений удобно определять индексные параметры в разделе констант:

Сonst Imax=10; Jmax=20; var Mas: array of integer;

Теперь для изменения размеров массива Mas и всех операторов программы, связанных с этими размерами, достаточно отредактировать только одну строку в программе - раздел констант.

Операции над массивами

Действия над массивом как единым целым. Такие действия допустимы лишь в двух случаях:

  • присваивание значений одного массива другому;
  • операции отношения «равно», «не равно».

В обоих случаях массивы должны иметь одинаковые типы (тип индексов и тип элементов). Пример:

Var P, Q: Array Of Real;

При выполнении операции присваивания P:= Q все элементы массива P станут равны соответствующим элементам массива Q.

В многомерных массивах переменная с индексом может обозначать целый массив. Например, если в таблице H требуется, чтобы данные за 1989 г. были такими же, как за 1981 г. (девятой строке присвоить значение первой строки), то это можно делать так:

Н := Н;

А если нужно поменять местами значения этих строк, то это делается через третью переменную того же типа:

Р:= Н; Н := Н; Н := Р;

где P описана так:

Var P: Array Of Real;

Обработка массивов

Обработка массивов в программах производится покомпонентно. Вот примеры ввода значений в массивы:

For I:= 1 to 12 do readln(T[I]); for I:= 1 to IMax do for J:= 1 to JMax do readln(Mas);

Здесь каждое следующее значение будет вводиться с новой строки. Для построчного ввода используется оператор read . Аналогично в цикле по индексной переменной организуется вывод значений массива. Например:

For I:= 1 tо 12 do write(T[I]:8:4);

Следующий фрагмент программы организует построчный вывод матрицы на экран:

For I:= 1 to IMax do begin for J:= l to JMax do write(Mas:6); writeln; end;

После печати очередной строки матрицы оператор writeln без параметров переведет курсор в начало новой строки. Следует заметить, что в последнем примере матрица на экране будет получена в естественной форме прямоугольной таблицы, если JMax не превышает 12.

Динамические массивы

Во FreePascal, Delphi добавлена интересная возможность описания массивов без указания размерностей и, соответственно, пределов изменения индексов:

Var IntArray: array of integer;

Такие массивы являются динамическими и изначально имеют нулевую длину. Установка размера массива и определение его во время выполнения программы производится так же как и для строк, с помощью функций SetLength и Length , соответственно. Элементы в данном случае нумеруются от нуля.

Program UsingDynamicArrays1; var А, В: Array of Integer; {Описание двух переменных - динамических массивов целочисленных элементов} begin SetLength(A, 5); {Установка размера массива А (5 элементов) } А := 1; {Присвоение значения 1 элементу массива А с номером 0 } end.

Переменные-динамические массивы являются указателями и операции с ними производятся как с указателями. Например, при присвоении одного массива другому элементы одного массива не копируются во второй, а копируется адрес массива. Соответственно, сравнение двух массивов в логических выражениях типа «равно - не равно» производится сравнением адресов. Пример присвоения одного массива другому:

Program UsingDynamicArrays2; var А, В: array of integer; {Описание двух переменных - динамических массивов целочисленных элементов} begin SetLength(A, 5); { Установка размера массива А (5 элементов) } А := 14; {Присвоение значения 14 нулевому элементу массива А} В:= А; {Присвоение массива А массиву В, теперь переменные А и В указывают на один и тот же массив} В := 2; {Присвоение нулевому элементу массива В значения 2, теперь нулевой элемент массива А также имеет значение 2} end.

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

Описание массива позволяет использовать в программе любой из его элементов. Для обозначения элементов массива в Си используются индексированные переменные.

Индексированная переменная (индексное выражение) – обозначение ячейки для хранения элемента массива. Именуется указанием идентификатора массива и индекса (индексов) элемента.

ü Внимание! Особенность обозначения элементов массива в Си - нумерация индексов от 0, а не от 1. Поэтому индексы в Си на единицу меньше заданных математически. Это обстоятельство должно учитываться в программе, особенно при формировании условия повторения (выхода из) цикла.

Схема распределения памяти для хранения одномерного массива такова:

Длина ячейки для хранения каждого элемента определяется типом массива:

· символьный – 1 байт;

· целочисленный – 2 байта;

· вещественный – 4 байта;

· двойной точности – 8 байт.

Структура обозначения индексированной переменной одномерного массива:

имя[индекс]

Где имя – идентификатор массива;

индекс – операнд целого типа, определяющий номер элемента в ряду других, составляющих массив;

– ограничители индекса.

Например, в описанном ранее массиве D(16) первый элемент обозначается индексным выражением d, второй – d, текущий – d[i], предпоследний – d и последний – d.

При необходимости индекс может задаваться арифметическим выражением. Например, d или d. В любом случае на момент использования переменной индекс должен быть определен (рассчитан) и полученное значение должно укладываться в заданный описателем диапазон.

Рассмотренный пример идентификации элементов массива D применим к любому из описанных одномерных массивов.

Индексированные переменные позволяют осуществить программную реализацию алгоритмов с использованием элементов массивов. При этом для одномерного массива индексированная переменная позволяет определить конкретный адрес каждого элемента.

Адрес любой переменной определяется операцией & . Следовательно, у элемента d адрес – &d, у d[i] – &d[i], т.е. все элементы массива располагаются в оперативной памяти линейно, начиная с адреса &d.



В языке Си идентификатор одномерного массива однозначно определяет адрес его первого элемента. Например, c º &c, d º &d.

Адрес каждого элемента одномерного массива выражается зависимостью имя+индекс (индекс определяет сдвиг элемента относительно первого на указанное им количество элементов). Например, &c[i] (адрес i-го элемента массива С) вычисляется как c+i.

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