Задача «Модули»

Постановка задачи. Определить, как соотносятся (больше, меньше или равно) суммы положительных, расположенных выше главной диагонали элементов двух матриц. Если суммы равны, то в каждой матрице найти индексы максимального по модулю элемента. Разработать программу для обработки матриц разного размера с использованием процедур и функций, реализованных в отдельном модуле. Необходимо выбрать подходящий тип подпрограмм – процедура или функция, для ввода и вывода матриц использовать процедуры. Ввод всех данных осуществляется из файла, вывод – в файл. Для передачи имён файлов должны использоваться параметры программы. Для каждой матрицы использовать своё заданное значение.

Шаг 1. Общая структура программы

Программа на процедурном языке программирования состоит из данных и действий по их обработке. program Units; { Описание данных – констант, типов и переменных } begin { Обработка данных } end.

Шаг 2. Разработка структуры данных

Из постановки задачи следует, что на вход программы подаются две квадратные матрицы a и b. Также должны быть заданы их размеры na и nb.

Из постановки задачи также следует, что в каждой матрице надо найти sa и sb – суммы положительных, расположенных выше главной диагонали элементов, а также ia, ja и ib, jb – индексы максимальных по модулю элементов.

Для задания массива введём константу, ограничивающую максимально возможное количество элементов массива, и тип для массива. program Units; const nmax = 10; type matrix = array [1..nmax, 1..nmax] of real; var { Входные данные } a, b: matrix; { Исходные матрицы } na, nb: integer; { Количество строк и столбцов в матрицах a и b соответственно } { Выходные данные } sa, sb: real; { Суммы в матрицах a и b соответственно } ia, ja, ib, jb: integer; { Индексы максимальных по модулю элементов в матрицах a и b соответственно } begin { Обработка данных } end.

Шаг 3. Разработка тестов

№ теста Входные данные Ожидаемые результаты Смысл теста
1 na = 3
a: 1   2   3
   4   5   6
   7   8  -9
nb = 3
b:  1   3   8
   12   5  -1
    7  -9   6
sa = sb = 11
ia = 3, ja = 3
ib = 2, ib = 1
Суммы одинаковы. Находим индексы максимальных по модулю элементов.
2 na = 3
a: 11   2  -3
    4   5   6
    7   8  -9
nb = 3
b:  1  -3   8
    1   5  -1
    7  -9   6
sa = sb = 8
ia = 1, ja = 1
ib = 3, ib = 2
Суммы одинаковы. Находим индексы максимальных по модулю элементов.
3 na = 3
a: 1  15  -6
   2   4   8
  -5  -7  -9
nb = 3
b: 3   4   2
  -8   3   1
   5  -3   7
sa = 23
sb = 7
Матрица a имеет большую сумму.
4 na = 3
a: 3   2   1
   6   2  -3
   5   0  12
nb = 2
b: 12  15
   24  37
sa = 3
sb = 15
Матрица b имеет большую сумму.

Шаг 4. Разработка общей структуры программы

Программа должна состять из трёх основных частей – ввод исходных данных, получение результатов, вывод полученных результатов. program Units; const nmax = 10; type matrix = array [1..nmax, 1..nmax] of real; var { Входные данные } a, b: matrix; { Исходные матрицы } na, nb: integer; { Количество строк и столбцов в матрицах a и b соответственно } { Выходные данные } sa, sb: real; { Суммы в матрицах a и b соответственно } ia, ja, ib, jb: integer; { Индексы максимальных по модулю элементов в матрицах a и b соответственно } begin { Ввод исходных данных } { Поиск сумм и максимальных по модулю элементов } { Вывод результатов } end.

Шаг 5. Выделение абстракций

Разработаем общий алгоритм решения задачи и посмотрим, какие абстракции можно будет в нём выделить. program Units; const nmax = 10; type matrix = array [1..nmax, 1..nmax] of real; var { Входные данные } a, b: matrix; { Исходные матрицы } na, nb: integer; { Количество строк и столбцов в матрицах a и b соответственно } { Выходные данные } sa, sb: real; { Суммы в матрицах a и b соответственно } ia, ja, ib, jb: integer; { Индексы максимальных по модулю элементов в матрицах a и b соответственно } begin { Ввод исходных данных } { Поиск сумм и максимальных по модулю элементов } Найти sa – сумму положительных, расположенных выше главной диагонали элементов матрицы a Найти sb – сумму положительных, расположенных выше главной диагонали элементов матрицы b Если sa > sb вывести соответствующее сообщение иначе если sa < sb вывести соответствующее сообщение иначе найти ia и ja – индексы максимального по модулю элемента матрицы a найти ib и jb – индексы максимального по модулю элемента матрицы b вывести полученные результаты end.

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

Шаг 6. Входная и выходная форма

Входная форма

Выходная форма

Шаг 7. Разработка структуры модулей

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

Файл UnitTypes.pas

unit UnitTypes; interface const nmax = 10; type matrix = array [1..nmax, 1..nmax] of real; implementation end.

Файл UnitInputOutput.pas

unit UnitInputOutput; interface uses UnitTypes; var fin, fout: TextFile; paramsExist, fExists: boolean; { Процедура ввода матрицы из файла } procedure Get(var x: matrix; var m, n: integer; var f: TextFile); { Процедура вывода матрицы в файл } procedure Put(const x: matrix; m, n: integer; name: string; var f: TextFile); implementation { Процедура ввода матрицы из файла } procedure Get(var x: matrix; var m, n: integer; var f: TextFile); var i, j: integer; begin readln(f, m, n); for i := 1 to m do begin for j := 1 to n do read(f, x[i, j]); readln(f); end; end; { Процедура вывода матрицы в файл } procedure Put(const x: matrix; m, n: integer; name: string; var f: TextFile); var i, j: integer; begin writeln(f, 'Матрица ', name, ' размером ', m:2, ' на ', n:2); for i := 1 to m do begin for j := 1 to n do write(f, x[i, j]:8:2); writeln(f); end; writeln(f); end; initialization if ParamCount < 2 then begin paramsExist := false; writeln('Недостаточно параметров!'); end else begin paramsExist := true; if not FileExists(ParamStr(1)) then begin fExists := false; writeln('Невозможно открыть файл ''', ParamStr(1), ''' для чтения'); end else begin fExists := true; AssignFile(fin, ParamStr(1)); Reset(fin); AssignFile(fout, ParamStr(2)); Rewrite(fout); end; end; finalization if fExists then begin CloseFile(fin); CloseFile(fout); end; end.

Шаг 8. Разработка интерфейса подпрограмм обработки матриц

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

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

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

Файл UnitComputing.pas

unit UnitComputing; interface uses UnitTypes; { Функция поиска суммы положительных элементов матрицы, расположенных выше главной диагонали } function Sum(const x: matrix; n: integer): real; { Процедура поиска индексов максимального по модулю элемента матрицы } procedure MaxIndexes(const x: matrix; m, n: integer; var imax, jmax: integer); implementation { Функция поиска суммы положительных элементов матрицы, расположенных выше главной диагонали } function Sum(const x: matrix; n: integer): real; var { Объявления локальных переменных } begin { Заглушка } result := 0; end; { Процедура поиска индексов максимального по модулю элемента матрицы } procedure MaxIndexes(const x: matrix; m, n: integer; var imax, jmax: integer); var { Объявления локальных переменных } begin { Заглушка } imax := m; jmax := n; end; end.

Шаг 9. Тестирование интерфейса подпрограмм

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

program Units; uses UnitTypes, UnitInputOutput, UnitComputing; var { Входные данные } a, b: matrix; { Исходные матрицы } na, nb: integer; { Количество строк и столбцов в матрицах a и b соответственно } { Выходные данные } sa, sb: real; { Суммы в матрицах a и b соответственно } ia, ja, ib, jb: integer; { Индексы максимальных по модулю элементов в матрицах a и b соответственно } begin if paramsExist and fExists then begin { Ввод исходных данных } Get(a, na, na, fin); Get(a, nb, nb, fin); { Обработка и вывод полученных результатов } Put(a, na, na, 'A', fout); Put(b, nb, nb, 'B', fout); sa := Sum(a, na); sb := Sum(b, nb); writeln('Сумма положительных элементов, расположенных выше главной диагонали, в матрице A = ', sa); writeln('Сумма положительных элементов, расположенных выше главной диагонали, в матрице B = ', sb); if sa > sb then writeln('Матрица A имеет большую сумму') else if sa < sb then writeln('Матрица B имеет большую сумму') else begin MaxIndexes(a, na, na, ia, ja); MaxIndexes(b, nb, nb, ib, jb); writeln('Суммы одинаковы'); writeln('Индексы максимального по модулю элемента в матрице A – ', ia, ', ', ja); writeln('Индексы максимального по модулю элемента в матрице B – ', ib, ', ', jb); end; end; end.

Шаг 10. Разработка подпрограмм

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

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

Файл UnitComputing.pas

unit UnitComputing; interface uses UnitTypes; { Функция поиска суммы положительных элементов матрицы, расположенных выше главной диагонали } function Sum(const x: matrix; n: integer): real; { Процедура поиска индексов максимального по модулю элемента матрицы } procedure MaxIndexes(const x: matrix; m, n: integer; var imax, jmax: integer); implementation { Функция поиска суммы положительных элементов матрицы, расположенных выше главной диагонали } function Sum(const x: matrix; n: integer): real; begin result := 0; for i: integer := 1 to n - 1 do for j: integer := i + 1 to n do if x[i, j] > 0 then result := result + x[i, j]; end; end; { Процедура поиска индексов максимального по модулю элемента матрицы } procedure MaxIndexes(const x: matrix; m, n: integer; var imax, jmax: integer); var max: real; begin max := abs(x[1, 1]); imax := 1; jmax := 1; for i: integer := 1 to n do for j: integer := 1 to n do if abs(x[i, j]) > max then begin max := abs(x[i, j]); imax := i; jmax := j; end; end; end.