Компания ALT Linux
Опубликован: 10.04.2015 | Доступ: свободный | Студентов: 762 / 0 | Длительность: 14:03:00
Специальности: Программист, Преподаватель
Лекция 6:

Обработка матриц в Паскале

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >

Матрица — это двумерный массив, каждый элемент которого имеет два индекса: номер строки и номер столбца.

Объявить двумерный массив (матрицу) можно так:

имя : array [ индекс1_нач.. индекс1_кон, индекс2_нач.. индекс2_кон ]

of тип;

где

  • тип определяет тип элементов массива,
  • имя — имя матрицы,
  • индекс1_нач..индекс1_кон — диапазон изменения номеров строк,
  • индекс2_нач..индекс2_кон — диапазон изменения номеров столбцов матрицы.

Например,

var h : array [ 0.. 1 1, 1.. 10 ] of integer;

Описана матрица целых чисел h, состоящая из двенадцати строк и десяти столбцов (строки нумеруются от 0 до 11, столбцы от 1 до 10).

Существует ещё один способ описать матрицы, для этого надо создать новый тип данных:

type

новый_тип=array [ индекс1_нач.. индекс1_кон ] of тип;

var

имя : array [ индекс2_нач.. индекс2_кон ] of новый_тип;

или

type

новый_тип=array [ список_диапазонов ] of тип;

var

имя : новый_тип;

Построчная обработка матрицы

Рис. 6.1. Построчная обработка матрицы
Алгоритм обработки матрицы по столбцам

Рис. 6.2. Алгоритм обработки матрицы по столбцам

Например:

type
massiv=array [ 1.. 30 ] of integer;
matrica=array [ 0.. 15, 0.. 13 ] of real;
var
a, b : array [ 1.. 10 ] of massiv;
c : matrica;

В данном случае в матрицах a и b есть 10 строк и 30 столбцов, а сматрица, в которой есть 16 строк и 14 столбцов.

Для обращения к элементу матрицы необходимо указать её имя и в квадратных скобках через запятую номер строки и номер столбца:

имя [ номер_строки, номер_столбца ]

или

имя [ номер_строки ] [ номер_столбца ]

Например, h[2,4]1Или h[2][4]. — элемент матрицы h, находящийся в строке под номером два и столбце под номером четыре.

Для обработки всех элементов матрицы необходимо использовать два цикла. Если матрица обрабатывается построчно, то во внешнем цикле последовательно перебираются строки от первой до последней, затем во внутреннем — все (первый, второй, третий и т. д.) элементы текущей строки. При обработке элементов матрицы по столбцам внешний цикл будет перебирать столбцы, внутренний — строки. На рис. 6.1 представлена блок-схема алгоритма обработки матрицы по строкам, на рис. 6.2 — по столбцам. Здесь i — номер строки, j — номер столбца, N — количество строк, M — количество столбцов матрицы A.

Блок-схема ввода элементов матрицы

Рис. 6.3. Блок-схема ввода элементов матрицы
Построчный вывод матрицы

Рис. 6.4. Построчный вывод матрицы

Рассмотрим основные операции, выполняемые над матрицами при решении задач.

6.1 Ввод-вывод матриц

Матрицы, как и массивы, нужно вводить (выводить) поэлементно. Вначале следует ввести размеры матрицы, а затем уже в двойном цикле вводить элементы. Блок-схема ввода элементов матрицы изображена на рис. 6.3.

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

2 3 13 35

5 26 76 37

52 61 79 17

Алгоритм построчного вывода элементов матрицы приведён на рис. 6.4.

Об описании матриц на языке Паскаль было рассказано в разделе 5.2 главы 5, обращение к элементу A_{i,j} матрицы можно осуществить c помощью конструкции A[i,j] или A[i][j].

Рассмотрим реализацию ввода-вывода матриц в консольных приложениях.

Для организации построчного ввода матрицы в двойном цикле по строкам и столбцам можно использовать оператор read.

for i :=1 to N do
for j :=1 to m do
read (A[ i, j ] );

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

ЗАДАЧА 6.1. Написать консольное приложение ввода матрицы вещественных чисел и вывода её на экран монитора.

Ниже приведён пример консольного приложения ввода-вывода матрицы.

var
a : array [ 1.. 2 0, 1.. 2 0 ] of real;
i, j, n,m: integer;
begin
{Ввод размеров матрицы}
writeln ( ’Введите количество строк и столбцов матрицы A ’ );
readln (N,M);
{Ввод элементов матрицы.}
writeln ( ’Введите_матрицу ’ );
for i :=1 to N do
for j :=1 to m do
read (A[ i, j ] );
{Вывод элементов матрицы.}
writeln ( ’матрица А  ’ );
for i :=1 to n do
begin
	for j :=1 to m do
		write ( a [ i, j ] : 8 : 3, ’   ’ ); {Печатается строка.}
	writeln {Переход на новую строку.}
end;

На рис. 6.5 представлены результаты работы программы.

Результаты работы программы решения задачи 6.1

Рис. 6.5. Результаты работы программы решения задачи 6.1

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

for i :=1 to N do
for j :=1 to m do
begin
write ( ’A( ’, i, ’, ’, j, ’ )= ’ );
	readln (A[ i, j ] )
end;

Авторы предлагают читателю самостоятельно разобраться, в чём будет отличие ввода матрицы в этом случае.

Для ввода-вывода матриц можно использовать компонент типа TStringGrid, с которым мы познакомились в главе 5.

В качестве примера рассмотрим следующую задачу.

ЗАДАЧА 6.2. Составить программу транспонирования2Транспонированная матрица — матрица, полученная из исходной матрицы A(N, M) заменой строк на столбцы. матрицы A.

Блок-схема транспонирования матрицы приведена на рис. 6.6. При транспонировании матрицы A(N, M ) получается матрица B(M, N).

Блок-схема транспонирования матрицы A

Рис. 6.6. Блок-схема транспонирования матрицы A

Рассмотрим частный случай транспонирования матрицы фиксированного размера A(4,3).

На форме разместим метки Label1 и Label2 со свойствами Caption — Заданная матрица A и Транспонированная матрица B, два компонента типа TStringGrid, изменив их свойства так, как показано в табл. 6.1, и кнопку Транспонирование матрицы.

Окно формы приложения представлено на рис. 6.7.

Ниже приведён текст подпрограммы с комментариями, которая будет выполняться, если пользователь щёлкнет по кнопке Транспонирование матрицы.

Таблица 6.1. Свойства компонентов StringGrid1, StringGrid2.
Свойство StringGrid1 StringGrid2 Описание свойства
Top 30 30 Расстояние от верхней границы таблицы до верхнего края формы
Left 15 240 Расстояние от левой границы таблицы до левого края формы
Height 130 130 Высота таблицы
Width 200 200 Ширина таблицы
ColCount 4 5 Количество столбцов
RowCount 5 4 Количество строк
DefaultColWidth 30 30 Ширина столбца
DefaultRowHeight 20 20 Высота строки
Options.goEditing true false Возможность редактирования таблицы
Форма приложения транспонирования матрицы

Рис. 6.7. Форма приложения транспонирования матрицы
procedure TForm1. Button1Click ( Sender : TObject );
const n=4;m=3; //Размерность матрицы A(n,m).
var
i, j : byte; //Индексы матрицы:
//i - строки, j - столбцы.
A: array [ 1.. n, 1..m] of integer; //Исходная матрица.
B: array [ 1.. m, 1.. n ] of integer; //Транспонированная матрица.
begin
//Исходные данные считываются из ячеек таблицы на форме,
//и их значения записываются в двумерный массив А.
for i :=1 to n do //Цикл по номерам строк.
for j :=1 to m do //Цикл по номерам столбцов.
//Считывание элементов матрицы A из компонента StringGrid1.
	A[ i, j ] : = StrToInt ( StringGrid1.Cells [ j, i ] );
//Формирование транспонированной матрицы B, см. блок-схему на
//рис. 6.6.
for i :=1 to n do //Цикл по номерам строк.
for j :=1 to m do //Цикл по номерам столбцов.
B[ j, i ] : =A[ i, j ];
//Элементы матрицы B выводятся в ячейки таблицы на форме.
for i :=1 to n do //Цикл по номерам строк.
for j :=1 to m do //Цикл по номерам столбцов.
//Обращение к элементам матрицы происходит по столбцам.
StringGrid2.Cells [ i, j ] : = IntToStr (B[ j, i ] );
end;

Результаты работы программы представлены на рис. 6.8.

Результаты работы программы транспонирования матрицы A(3,4)

Рис. 6.8. Результаты работы программы транспонирования матрицы A(3,4)

Для демонстрации ввода-вывода матриц с помощью компонента типа TStringGrid мы рассмотрели работу с матрицами фиксированного размера A(4,3) и B(3,4). Теперь рассмотрим общий случай решения задачи транспонирования матрицы A(N,M).

Расположим на форме следующие компоненты:

  • метку label1 с надписью "Введите размерность матрицы";
  • метку label2 с надписью "N=";
  • метку label3 с надписью "M=";
  • метку label4 с надписью "Исходная матрица А";
  • метку label5 с надписью "Преобразованная матрица В";
  • поле ввода Edit1 для ввода числа N;
  • поле ввода Edit2 для ввода числа M;
  • компонент StringGrid1 для ввода исходной матрицы A;
  • компонент StringGrid2 для хранения транспонированной матрицы B;
  • кнопку Button1 с надписью "Ввод" для ввода размеров матрицы А;
  • кнопку Button2 с надписью "Очистить" для очистки содержимого матриц;
  • кнопку Button3 с надписью "Транспонирование" для решения задачи транспонирования матрицы А;
  • кнопку Button4 с надписью "Выход из программы" для завершения работы программы.

Можно разместить компоненты на форме так, как показано на рис. 6.9.

Окно формы решения задачи транспонирования матрицы A(N, M )

увеличить изображение
Рис. 6.9. Окно формы решения задачи транспонирования матрицы A(N, M )
Стартовое окно программы транспонирования матрицы A(N, M )

увеличить изображение
Рис. 6.10. Стартовое окно программы транспонирования матрицы A(N, M )

Установим свойство видимости (Visible) в False у компонентов метки label4, label5, StringGrid1, StringGrid2, кнопки Button2 и Button3. После этого при запуске программы будут видны только компоненты, отвечающие за ввод размеров матрицы, и кнопка Выход из программы (см. рис. 6.10) 3Свойству формы Caption присвоено значение Транспонирование матрицы.. Матрицы A и B, их размеры N, M объявим глобально.

type
	{ TForm1 }
{Описание формы}
	TForm1 = class (TForm)
		Button1 : TButton;
		Button2 : TButton;
		Button3 : TButton;
		Button4 : TButton;
		Edit1 : TEdit;
		Edit2 : TEdit;
		Label1 : TLabel;
		Label2 : TLabel;
		Label3 : TLabel;
		Label4 : TLabel;
		Label5 : TLabel;
		StringGrid1 : TStringGrid;
		StringGrid2 : TStringGrid;
	private
	{private declarations}
	public
	{public declarations}
end;
var
{Матрицы A,B}
	A,B: array [ 1.. 25, 1.. 25 ] of integer;
{и их размеры}
	N,M: integer;
	Form1 : TForm1;

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

procedure TForm1. Button4Click ( Sender : TObject );
begin
	Close;
end;

Теперь напишем обработчик кнопки Ввод, который должен вводить и проверять корректность введения размеров матрицы, устанавливать свойства компонентов StringGrid1 и StringGrid2 (количество строк и столбцов), делать видимым компонент StringGrid1, кнопку Транспонирование, невидимыми компоненты, отвечающие за ввод размеров матрицы (метки label1, label2, label3, поля ввода Edit1 и Edit2, кнопку Ввод ).

procedure TForm1. Button1Click ( Sender : TObject );
var i : byte; kod_n, kod_m, kod : integer;
begin
//Ввод размерности матрицы.
//Символьная информация преобразовывается в числовую и
//записывается в
	Val ( Edit1. Text,N, kod_m ); //переменную M
	Val ( Edit2. Text,M, kod_n ); //и переменную N.
//Если преобразование прошло успешно и введенные размеры
//удовлетворяют описанию
//матриц A и B,
	if ( kod_n=0) and (kod_m=0) and (N>0) and (N<26) and (M>0)
		and (M<26)
	then
//то
	begin
//визуализируется первая матрица,
		StringGrid1. Visible := true;
		Label4. Visible := true; //соответствующая ей надпись,
		Button2. Visible := true; //кнопки "Очистить"
		Button3. Visible := true; //и "Транспонирование".
		with StringGrid1 do
		begin
//Определяем число строк (RowCount) и столбцов(ColCount) в
//компоненте StringGrid1.
			ColCount :=M+1;
			RowCount:=N+1;
//и нумеруем строки и столбцы матрицы.
			for i :=1 to RowCount-1 do
			Cells [ 0, i ] : = IntToStr ( i );
			for i :=1 to ColCount -1 do
			Cells [ i, 0 ] : = IntToStr ( i );
		end;
StringGrid2. ColCount :=N+1;
StringGrid2. RowCount:=M+1;
end
	else
	begin
//При некорректном вводе выдаётся соответствующее сообщение.
	MessageDlg ( ’Размеры матрицы введены не верно ! ’, MtInformation,
[mbOk ], 0 );
//Устанавливаются стартовые параметры в поля ввода.
	Edit1. Text := ’ 4 ’;
	Edit2. Text := ’ 3 ’;
end;
end;

Теперь напишем обработчик кнопки Транспонирование. При щелчке по этой кнопке становится видимым компонент StrigGrid2, предназначенный для хранения транспонированной матрицы B, соответствующая ему надпись (label5), формируется матрица B. Матрица B выводится в компонент StringGrid2. Кнопка Ввод становится невидимой. Текст обработчика приведён ниже.

procedure TForm1. Button2Click ( Sender : TObject );
var i, j : integer;
begin
//Визуализируется вторая матрица,
//соответствующая ей надпись.
StringGrid2. Visible := true;
label5. Visible := true;
for i :=1 to N do //Цикл по номерам строк.
for j :=1 to M do //Цикл по номерам столбцов.
//Считывание элементов матрицы A из компонента StringGrid1.
A[ i, j ] : = StrToInt ( StringGrid1.Cells [ j, i ] );
with StringGrid2 do
begin
for i :=1 to RowCount-1 do //Нумеруются строки
Cells [ 0, i ] : = IntToStr ( i );
for i :=1 to ColCount -1 do //и столбцы компонента StringGrid2, в
Cells [ i, 0 ] : = IntToStr ( i ); //котором отображается матрица B.
end;
//Формирование транспонированной матрицы B.
for i :=1 to N do //Цикл по номерам строк.
for j :=1 to M do //Цикл по номерам столбцов.
B[ j, i ] : =A[ i, j ];
//Элементы матрицы B выводятся в ячейки таблицы на форме.
for i :=1 to n do //Цикл по номерам строк.
for j :=1 to m do //Цикл по номерам столбцов.
//Обращение к элементам матрицы происходит по столбцам.
StringGrid2.Cells [ i, j ] : = IntToStr (B[ j, i ] );
Buuton1.Visible := False;
end;

Осталось написать обработчик события при нажатии на кнопку Очистить. При щелчке по этой кнопке должно происходить следующее:

  • очистка содержимого компонентов StringGrid1, StringGrid2;
  • компоненты StringGrid1, StringGrid2 и соответствующие им метки labe4 и label5, а также кнопки Транспонировать и Очистить становятся невидимыми;
  • становится видимой кнопка Ввод;
  • в поля ввода записываются начальные значения размеров матрицы (N=4, M=3).

Текст обработчика кнопки Очистить с комментариями приведен ниже:

procedure TForm1. Button3Click ( Sender : TObject );
var i, j : integer;
begin
//Очистка компонента StringGrid1.
	with StringGrid1 do
		for i :=1 to RowCount-1 do
		for j :=1 to ColCount -1 do
			Cells [ j, i ] : = ’ ’;
//Очистка компонента StringGrid2.
	with StringGrid2 do
		for i :=1 to RowCount-1 do
		for j :=1 to ColCount -1 do
		Cells [ j, i ] : = ’ ’;
//Делаем невидимыми компоненты StringGrid1, StringGrid2,
//labe4, label5.
	StringGrid1. Visible := False;
	StringGrid2. Visible := False;
	label4. Visible := False;
	label5. Visible := False;
//Делаем невидимыми кнопки "Транспонировать" и "Очистить".
	Button2. Visible := False;
	Button3. Visible := False;
//Делаем видимой кнопку "Ввод".
	Button1. Visible :=True;
//Запись начальных значений размеров матрицы
//(N=4, M=3).
	Edit1. Text := ’ 4 ’;
	Edit2. Text := ’ 3 ’;
end;

Мы получили работающую программу для транспонирования матрицы. На рис. 6.11 представлены результаты транспонирования матрицы A(2,4).

Обратите внимание на использование оператора присоединения

with имя_компонента do оператор;

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

Например, для очистки элементов матрицы A вместо операторов

for i :=1 to StringGrid1. RowCount-1 do
	for j :=1 to StringGrid1. ColCount -1 do
		StringGrid1.Cells [ j, i ] : = ’ ’;

был использован оператор

with StringGrid1 do
	for i :=1 to RowCount-1 do
		for j :=1 to ColCount -1 do
			Cells [ j, i ] : = ’ ’;

Рассмотрим несколько задач обработки матриц. Для их решения напомним читателю некоторые свойства матриц (рис. 6.12):

Транспонирование матрицы A(2,4)

увеличить изображение
Рис. 6.11. Транспонирование матрицы A(2,4)
Свойства элементов матрицы

Рис. 6.12. Свойства элементов матрицы
  • если номер строки элемента совпадает с номером столбца (i = j), это означает, что элемент лежит на главной диагонали матрицы;
  • если номер строки превышает номер столбца (i > j), то элемент находится ниже главной диагонали;
  • если номер столбца больше номера строки (i < j), то элемент находится выше главной диагонали;
  • элемент лежит на побочной диагонали, если его индексы удовлетворяют равенству i + j - 1 = n;
  • неравенство i + j - 1 < n характерно для элемента, находящегося выше побочной диагонали;
  • соответственно, элементу лежащему ниже побочной диагонали, соответствует выражение i + j - 1 > n.
< Лекция 5 || Лекция 6: 123456 || Лекция 7 >
Юрий Шутиков
Юрий Шутиков

По первому тесту выполнил дважды задания. Результат получается правильный (проверял калькулятором). Пишет, что "Задание не проверено" и предлагает повторить. 
 

Евгений Силуков
Евгений Силуков

Еще в декабре выполнил тест №1, а его все так и не проверили.