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

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

Var

TwoDimensionalArray: Array [1..80, 1..25] of Char;

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

Поскольку элементы массивов расположены упорядоченно в соответствии с их номерами-индексами, необходимо внимательно относиться к изменению индексов. Обработка таких одномерных массивов ведется, как правило, с использованием вложенных циклов For…to…do.

Пример:

Применение некоторого двумерного массива.

Переменные Line и Column определяют номера строк и столбцов на экране.

Program DemoUsesTwoDimensionalArray;

Uses Crt;

Var

TwoDimensionalArray: Array[18..0, 1..25] of char;

Column, Line: integer;

Begin

ClrScr;

for Line:= 1 to 25 do

for Column: = 1 to 80 do

TwoDimensionalArray[Column, Line]:= Chr(32+Column);

{Вывод элементов массива. Номер столбца изменяется чаще}

{номера строки}

ClrScr;

for Line:= 1 to 25 do

begin

for Column: = 1 to 80 do

Write(TwoDimensionalArray[Column, Line]);

Writeln;

end;

End.

Пример:

Программа, которая выполняет «зеркальное» отображение элементов матрицы размерности m*n, элементами которой являются целые числа. Отображение осуществляется относительно вертикальной оси симметрии (меняет местами элементы первого столбца с последним, второго с предпоследним и т.д.).

Program VertMirrow;

Const

m = 10; {число строк}

n = 15; {число столбцов}

type

TMatr= array[1..m, 1..n] of integer;

Var

Matr: TMatr;

B: Integer;

i, j: integer;

Begin

Clrscr;

for i: =1 to m do {Ввод исходных значений матрицы}

for j: =1 to n do

readln(Matr[i, j]);

writeln ('Исходная матрица');

for i: =1 to m do

begin

for j: =1 to n do write (Matr [i, j]: 5);

writeln;

end;

writeln;

{Зеркальное отображение матрицы относительно вертикальной}

{оси симметрии}

for j: =1 to n div 2 do (Берем столбцы от первого до среднего)

for i: =1 to m do (Меняем местами симметричные столбцы)

begin

B:= Matr[i, j];

Matr[i,j]:= Matr [i, n-j+1];

Matr[i, n-j+1]:= B;

end;

Writeln('Преобразованная матрица:');

for i: =1 to m do

begin

for j: =1 to n do write (Matr [i, j]: 5);

writeln;

end;

writeln;

End.

Пример:

Программа, осуществляющей вывод элементов квадратной матицы порядка n и вывод, выполняя обход матрицы по «спирали», как показано на рисунке.

  i p p+1 n–p n–p+1   j p n–p+1   p p+1 n–p+1
1 2 3 4 5 6
           
           
           
           
           
           
p n–p n–p+1

P –номер текущего витка «Спирали»

Программа, соответствующая данной схеме, имеет вид:

Program SpiralWrite;

Uses Crt;

const

n =10; {порядок квадратной матрицы}

type

TMatr = array[1…n, 1…n]of integer;

Var

Matr: TMatr; {исходная матрица}

i, j, p: integer;

Begin

ClrScr;

for i: =1 to n do

begin

for j: = 1 to n do read(Matr [i,j]);

end

writeln ('Исходная матрица:');

for i: = 1 to n do

begin

for j: = 1 to n do

write(Matr [i,j]:5);

writeln;

end;

writeln;

{Выписывание элементов матрицы по «спирали»}

for p: = 1 to (n+1) div 2 do

begin

{Выписывание элементов верхней строки p–го витка}

for j: =p to n-p+1 do

write(Matr[p, j]:4);

{Выписывание элементов правого столбца p–го витка}

for i: =p+1 to n-p+1 do

write(Matr[i,n-p+1]:4);

{Выписывание элементов нижней строки p–го витка}

for j: =n-p downto p do

write(Matr[n-p+1,j]:4);

{Выписывание элементов левого столбца p–го витка}

for i: =n-p downto p+1 do

write(Matr[i,p]:4);

end;

End.

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

Var

a,b: array [1…5]of integer;

begin

....

a: =b

....

end.

После этого присваивания все пять элементов массива a получат те же значения, что и в массиве b. Однако над массивами не определены операции отношения. Нельзя, например, записать: if a =b then…

Сравнить два массива можно поэлементно, например:

Var

a,b: array [1…5] of singl;

eq: Boolean;

i: byte;

Begin

....

eq: = true;

for i: = 1 to 5 do

if a[1]< > b[j] then

eq: =fals;

if eq= false then

....

End.

Задачи

1. Заполнить два массива размера n´n, все элементы которого целые числа. Вычислить сумму двух массивов.

2. Заполнить массив размера n´n, все элементы которого целые числа, затем ввести число. Вычислить произведение матрицы на число.

3. Заполнить массив размера n´n, все элементы которого целые числа. Преобразовать массив, заменив строки столбцами.

4. Заполнить массив размера n´n, все элементы которого целые числа. Преобразовать его:

а) расставив строки в порядке возрастания первого элемента каждой строки;

б) расставив строки в порядке убывания первого элемента каждой строки;

в) расставить столбцы в порядке возрастания первого элемента каждого столбца;

г) расставить столбцы в порядке убывания последнего элемента каждого столбца.

5. Усложнить предыдущую задачу условием: в случае равенства первых элементов провести расстановку по вторым элементам, затем в случае равенства вторых – по третьим и т.д.

6. Заполнить массив размера n´n, все элементы которого целые числа. Вывести на экран:

а) строки, первые элементы которых – четные числа;

б) строки, первые элементы которых – положительные числа;

в) строки, сумма элементов которых – четное число;

г) столбцы, первые элементы которых – положительные числа;

д) столбцы, первые элементы которых – четные числа;

е) те строки, где элемент главной диагонали массива – четное число.

7. Заполнить массив размера n´n, все элементы которого натуральные числа. Подсчитать число комбинаций символов 'н', 'о'. Комбинации 'но', 'он', , входят в это число.

8. Заполнить случайным образом массив n´n, все элементы которого целые числа. Вывести на экран максимальные элементы строк.

9. Заполнить случайным образом массив размера n´n, все элементы которого целые числа. Получить новый массив, переставляя его блоки в соответствии с рисунком:

а) б)

       
   


10. Заполнить случайным образом массив размера n´n. Определить максимальный элемент в заштрихованной области.

а) б) в)

       
   


ЗАПИСИ

Рассмотрим еще один структурированный тип данных, так называемые записи (Record), позволяющие хранить вместе переменные, имеющие различные типы данных:

Структура объявления типа записи такова:

<имя типа> = RECORD <список полей> End;

Каждый раздел записи состоит из одного или нескольких идентификаторов полей, отделяемых друг от друга запятыми. За идентификаторами ставится двоеточие и описание типа поля (полей), например:

type

Birthday = record

day, month: byte;

year: integer;

end;

var

a,b: Birthday;

В этом примере тип Birthday (день рождения) есть запись с полями day, month и year (день, месяц и год); переменные А и В содержат записи типа Birthday.

Как и в массиве, значения переменных типа записи можно присваивать переменным того же типа, например:

a: =b;

К каждому из компонентов записи можно получить доступ, если использовать составное имя, т.е. указать имя переменной, затем точку и имя поля:

a.day: =27

b.year: =1939;

Для вложенных полей приходится продолжать уточнения:

type

Birthday = record

day, month: byte;

year: integer;

end;

var

c: record

name: string;

bd: Birthday;

end;

begin

....

if c.bd.year =1939 then…

end.

Чтобы упростить доступ к полям записи, используется оператор присоединения with:

With <переменная> do <оператор>

Здесь With, do – ключевые слова (с, делать);

<переменная> – имя переменной типа запись, за которым, возможно, следует список вложенных полей;

<оператор> – любой оператор Турбо Паскаль.

Например:

With c.bd do month: =9;

это эквивалентно:

With c do With bd do month: =9;

Турбо Паскаль разрешает использовать записи с так называемыми вариативными полями, например:

Type

Forma =record

Name: string;

case byte of

0: (Birth Place: string [40]);

1: (Country: string [20];

Entri Port: string [20];

Entry Pate: 1…31;

Exite Pate: 1…31)

End;

В этом примере тип FORMA определяет запись с одним фиксированным полем Name и вариативной частью, которая задается предложением case of. Вариативная часть состоит из нескольких вариантов (в примере для двух вариантов: 0 и 1). Каждый вариант определяется константой выбора, за которой следует двоеточие и список полей, заключенный в круглые скобки. В любой записи может быть только одна вариативная часть, и, если она есть, то должна располагаться за всеми фиксированными полями.

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

Var

met 4: record

case byte of

0: (by: array [0…3]of byte);

1: (wo: array [0…1]of word);

2: (lo: longint);

end;

В этом примере запись met 4 имеет три варианта, каждый из которых занимает в памяти один и тот же участок в 4 байт. В зависимости от того, к какому полю мы обращаемся в программе, этот участок может рассматриваться как массив из 4 байт (поле by) массив из двух целых типа Word или, наконец, как одно целое число типа Longint. Например, этой записи можно сначала присвоить значение как длинному целому, а затем проанализировать результат по байтам или словам.

Var

x: word;

xb: byte;

xl: LongInt;

Begin

....

with m do

begin

lo:= trunc(2*pi*x);

if wo[1]=0 then

if wo[1] =0 then

xb: =x[0]

else

x:= wo[0]

else

x1: =lo

end;

....

End.

Предложение CASE…OF, открывающее вариативную часть, внешне похоже на соответствующий оператор выбора, но на самом деле играет лишь роль своеобразного служебного слова, обозначающего начало вариативной части. Именно поэтому в конце вариативной части не следует ставить END как пару к CASE…OF (Поскольку вариативная часть всегда последняя в записи, за ней все же стоит END, но лишь как пара к RECORD)

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

Это, однако, не влияет на выбор поля. Значения констант выбора в Турбо Паскаль могут быть производными, в том числе повторяющимися, например:

type

rec1= record

a: byte;

b: word;

end;

rec 2 =record

c: longint;

case x: byte of

1: (d: word);

2: (e: record case Boolean of

3: (f: rec 1);

3: (g: single);

'3': (c: word)

end)

end;

var

r: rec2;

begin

r.x:= 255;

if r.e.g =0 then

writeln('O.K.')

else

writeln (r.e.g.);

End.

В этом предложении case Boolean of в записи, определяемой в поле Е, объявляет ключом выбора логический тип, который, как известно, имеет лишь значения TRUE и FALSE. Константы же выбора следующих далее вариантов не только содержат совершенно не свойственные этому типу значения, но и две из них повторяющиеся, а общее количество вариантов три, а не два, как следовало бы ожидать.

Имена полей должны быть уникальными в пределах той записи, где они объявлены, однако, если записи содержат поля-записи, т.е. вложены одна в другую, имена могут повторяться на разных уровнях вложенности.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: