Многомерные статические массивы
Если четыре причины возможных неприятностей
заранее устранены, то всегда найдется пятая.
Из законов Мэрфи.
Каждый элемент массива, в свою очередь, может являться массивом. Это позволяет создавать двумерные таблицы (матрицы), трехмерные (представьте себе прямоугольный параллелепипед), а также массивы с большим числом измерений. Зачем может понадобиться четырехмерный массив, который и представить-то сложно? Вот пример: в комнате в точках с координатами x,y,z меряется температура t. Тогда данные о температуре легче всего представить в виде четырехмерного массива [x,y,z,t].
Чаще всего встречаются двумерные массивы. Для их описания в операторе TYPE указывают не одну, а две размерности:
TYPE TA=ARRAY[1..10, 1..5] OF REAL;
В таком массиве всего 10´5=50 элементов, а для обращения к любому из них нужно указывать два индекса: a[i, j].
К сожалению, во многих книгах по программированию усиленно муссируется вопрос про "строки" и "столбцы" двумерного массива. На самом деле никаких строк и столбцов в памяти компьютера не возникает, массив любой размерности хранится линейно. Соответственно и вопрос "а что указывать первым – число строк или столбцов?" – лишен смысла. Вы можете для удобства считать, что первым индексом является номер строки, а вторым – номер столбца, или наоборот – это ни на что не повлияет.
Для обработки двумерных массивов нужны вложенные циклы. Один цикл находится внутри другого и при каждой итерации внешнего цикла внутренний цикл пробегает все заданные значения. Рассмотрим пример заполнения двумерного массива случайными числами и нахождения среднего арифметического его элементов:
CONST MaxX=10, MaxY=20;
TYPE TA=ARRAY[1..MaxX, 1..MaxY] OF REAL;
VAR a:TA; i, j: BYTE; s:REAL;
BEGIN
s:=0;
FOR i:=1 TO MaxX DO
FOR j:=1 TO MaxY DO
BEGIN
a[i,j]:=random;
s:=s+a[i,j]
END;
s:=s/(MaxX*MaxY);
Label1.Caption:=
'Максимальный элемент равен '+FloatToStrF(max,ffFixed,10,4);
Ввод-вывод массивов
Лифт ломается чаще, чем лестница.
Из законов Мэрфи
Ввод с клавиатуры
Чаще всего массив нужно не заполнять случайными значениями, а вводить с клавиатуры или считывать из файла. Для ввода значений пользователем удобнее всего использовать компонент TStringGrid , находящийся на закладке Additional. Он представляет собой таблицу с произвольно задаваемым числом столбцов и строк, в каждую ячейку которой можно вводить и выводить данные (Рис. 5).
Рис. 5 – Компонент TStringGrid.
Основными свойствами компонента TStringGrid являются:
ColCount – общее число столбцов, включая фиксированные;
RowCount – общее число строк, включая фиксированные;
DefaultColWidth – ширина каждого столбца в пикселах:
DefaultRowHeight – высота каждой строки в пикселах;
FixedCols, FixedRows – число фиксированных столбцов и строк соответственно. Фиксированные столбцы и строки выделены цветом (она задается в свойстве FixedColor) и остаются на месте при прокрутке содержимого таблицы, поэтому в них очень удобно задавать заголовки столбцов и строк;
ScrollBars – управляет отображением полос прокрутки. Возможные значения: ssNone (нет), ssHorizontal (только горизонтальная полоска), ssVertical(только вертикальная полоска), ssBoth (обе полоски);
GridLineWidth – задает толщину линий сетки в пикселах.
Свойство Options представляет собой множество значений, управляющих работой TStringGrid. Среди этих значений:
goFixedVertLine – отображать вертикальные линии для фиксированных ячеек таблицы;
goFixedHorzLine– отображать горизонтальные линии для фиксированных ячеек таблицы;
goVertLine - отображать вертикальные линии для обычных ячеек таблицы;
goHorzLine- отображать горизонтальные линии для обычных ячеек таблицы;
goRangeSelect – возможность выделения диапазона ячеек, если отключен ввод данных в ячейки с клавиатуры;
goDrawFocusSelected – выделение редактируемой ячейки цветом;
goRowSizing – возможность изменения высоты строк пользователем;
goColSizing – возможность изменения ширины столбцов пользователем;
goRowMoving – возможность изменения порядка следования обычных строк при перетягивании их мышкой;
goColMoving - возможность изменения порядка следования обычных столбцов при перетягивании их мышкой;
goEditing – возможность ввода значений в ячейки таблицы пользователем с клавиатуры;
goTabs – клавиша Tab обеспечивает переход от ячейки к ячейке;
goRowSelect – выделение не отдельной ячейки, а целой строки;
goAlwaysShowEditor – постоянно включен режим редактирования содержимого ячеек и отображается текстовый курсор;
goThumbTracking – содержимое таблицы перерисовывается "на ходу", в процессе перетаскивания линеек прокрутки.
Для доступа из программы к содержимому каждой ячейки применяется массив Cells[столбец, строка]. Нумерация строк и столбцов ведется с нуля! Данные в ячейках хранятся как текст (тип данных String), поэтому при работе с числами необходимо выполнять преобразование.
Организуем ввод с клавиатуры двумерного массива вещественных чисел 4´5 элементов и найдем его максимальный элемент. Положим на форму компонент TStringGrid и установим его свойства следующим образом:
ColCount=4;
RowCount=5;
DefaultColWidth=50;
DefaultRowHeight=50;
FixedCols=0;
FixedRows=0;
ScrollBars=ssNone;
Options=[goEditing, goDrawFocusSelected]
Кстати, число строк и колонок можно задавать и программным путем, тем самым меняя размер таблицы на ходу. Поместим на форму кнопку, компонент Label и в обработчике ее нажатия запишем следующий код:
VAR i,j:BYTE;
max:REAL;
begin
WITH StringGrid1 DO
BEGIN
max:=StrToFloat(Cells[1,1]);
FOR i:=1 TO ColCount-1 DO
FOR j:=1 TO RowCount-1 DO
IF StrToFloat(Cells[i,j])>max THEN
max:=StrToFloat(Cells[i,j]);
Label1.Caption:='Max='+FloatToStrF(max,ffFixed,10,4)
END
end;
Как видно, нет необходимости копировать введенные числа в статический массив – можно напрямую работать с массивом Cells.
В приведенном примере для простоты отсутствует защита от ввода неверных значений. В реальной программе, разумеется, надо ставить оператор TRY…EXCEPT.
Для вывода информации в виде массива нужно просто присваивать значения элементам массива Cells. Например, так можно заполнить заголовки (ячейки фиксированной строки). Строка
StringGrid1.Cells[0,0]:='Длина, мм';
занесет значение "Длина, мм" в левую верхнюю ячейку таблицы.