2. Пример использования DLLПолностью два варианта приложения, использующих библиотеку, размещены в прилагаемых каталогах primer_tema3vopr2dll и InterfForTopDown (архивы .rar). Цель приводимого ниже текста – пояснение основных моментов, касающиеся разработки библиотеки. 2.1. Разработка процедуры, заносимой в библиотеку В рамках задания по лабораторной работе № 4 для задачи top_down оформим обработку данных (т.е. собственно решение задачи) в виде процедуры и запишем в библиотеку DLL. Будем базироваться на имеющейся разработке (см. курс «Технология разработки ПО», тема 3, вопрос 2). Здесь на уровне 0 проектирования алгоритма обработка совмещена с выводом результатов и представлена абстракцией А0.3: ....................... {решение задачи} {вх.: n, b, m, a; вых.: a или maxmin} А0.3. <решение задачи с выводом результатов по обр 3> ....................... Чтобы процедура решения была пригодна для использования во всех вариантах приложения (т.е. вариантах с разными интерфейсами), из нее следует убрать ввод-вывод. Задача имеет три варианта решения, или три вида результатов, каждому из которых соответствует своя форма (см. уровень 1, задача А0.3): Обр 3.1 | Результаты | | Обр 3.2.1 | Измененная матрица: | 1-й вариант решения | Обр 3.2.2 (совпадает с обр 2.4) | <a(1,1)> <a(1,2)> . . . <a(1,n)> . . . . . . . . <a(m,1)> <a(m,2)> . . . <a(m,n)> | Обр 3.2.3 | В массиве b есть одинаковые элементы, но матрица не содержит
строки со всеми положительными элементами и не меняется | 2-й вариант | Обр 3.2.4 | Максимальное значение минимумов строк матрицы = < maxmin > | 3-й вариант |
Разделить обработку и вывод можно так: помимо входных и выходных данных задачи, включим в состав параметров процедуры дополнительный параметр, соответствующий варианту решения. В зависимости от значения этого параметра после вызова процедуры будет выводиться соответствующий вариант результатов. Тогда абстракция A0.3 уровня 0 детализируется следующим образом: A0.3a <Решение задачи с фиксацией варианта решения> A0.3b <Анализ варианта решения и вывод по соответствующему образцу> Разработка процедуры для задачи А0.3a выполняется обычным образом и приведена ниже. 1. Задача А0.3aЕсли в одномерном целочисленном массиве b есть хотя бы два одинаковых элемента, то заменить первую строку матрицы a , все элементы которой больше нуля, на этот массив, иначе найти максимальное значение минимальных элементов строк матрицы. 2. Входные данныецел n - число элементов массива b; число столбцов матрицы a; простая переменная; цел m - число строк матрицы a; простая переменная; цел b - исходный одномерный массив; цел a - исходная матрица; двумерный массив. Данные во внутреннем представлении (так как к моменту решения задачи А0.1 они введены); входная форма отсутствует. 3. Выходные данныецел a - измененная матрица; цел maxmin - максимальное значение минимальных элементов строк; простая переменная. цел resvar – вариант решения; 1, изменение матрицы; resvar = 2, поиск максимального значения минимальных элементов строк матрицы; 3, обработка не производится (ситуация, когда в массиве b есть хотя бы два одинако- вых элемента, но в матрице нет строки со всеми положительными элементами) Оформление процедуры Вид - общего вида Имя – reshenie Поскольку процедура вызывается один раз, выберем для формальных параметров те же имена, что и для фактических. • Заголовок - проц reshenie (n, m, b,a, maxmin, resvar); Обращение - reshenie (n, m, b,a, maxmin, resvar);• Описание на псевдокоде {поиск строки со всеми положит. элементами в матрице} проц reshenie (n, m, b,a, maxmin, resvar); арг цел n, m; цел b(n), a(m,n); рез цел a(m,n); цел maxmin, resvar; нач <описания локальных переменных> <алгоритм тела процедуры> кон; кон reshenie; Разработка заглушки Алгоритм заглушки (тело процедуры) Для теста 1.1 (в массиве b есть два равных элемента и искомая строка есть): {Измененная матрица} a[1,1]:= -1; a[1,2]:= 0; a[1,3]:=2; a[1,4]:= -3; a[2,1]:= 2; a[2,2]:= -1; a[2,3]:=0; a[2,4]:= 2; a[3,1]:= 1; a[3,2]:= 2; a[3,3]:=3; a[3,4]:= 1; resvar:=1; Для теста 1.2 (в массиве b нет равных элементов): { Максимальное значение минимальных элементов строк матрицы } maxmin:=1; resvar:=2; Для теста 1.3 (в массиве b есть два равных элемента, но искомой строки нет): { Обработка не производится } resvar:=3; Кодирование процедуры на паскале Определение глобальных объектов Глобальный тип и константы для параметров a и b определены при кодировании процедур проверки массивов: const nmax=50; mmax=50; type arrb=array[1..nmax] of integer; arra=array[1..mmax, 1..nmax] of integer; Описание процедуры procedure reshenie (n,m :integer; var b:arrb; var a:arra; var maxmin: integer; var resvar: byte);
var <описания локальных переменных>; begin <операторы> end; Обращение к процедуре: reshenie (n,m, b, a, maxmin, resvar); 2.2. Структура и содержание библиотеки Пусть создаваемая библиотека имеет имя TopDownDLL.dll. Только для консольного варианта с иллюстративной целью в библиотеку внесены еще процедуры проверки массивов. Для корректной локализации описаний файловые переменные выходных файлов, куда записывается диагностика ошибок, включены в список параметров (в исходном варианте процедуры были внутренними, а файловые переменные передавались как глобальные). Текст файла проекта библиотеки TopDownDLL.dpr приведен ниже. library TopDownDLL; uses SysUtils, Classes; {$R *.res} {описания констант и типов, глобальных для процедур} const nmax=50; mmax=50; type arrb=array[1..nmax] of integer; arra=array[1..mmax,1..nmax] of integer; {описания процедур} {проверка массива b} procedure provb(n:integer; var b:arrb; var bver:boolean; var res:text); var i:byte; {локальная величина} begin ....... end; {проверка массива a} procedure prova(m, n:integer; var a:arra; var aver:boolean; var res:text); var i,j:byte; {локальная величина} begin ...... end; {Решение. Вместо обработки заглушки} procedure reshenie (n,m :integer; var b:arrb; var a:arra; var maxmin: integer; var resvar: byte); var {<описания локальных переменных>}; begin ..... end; exports //список экспортируемых функций provb, prova, reshenie; begin end. 2.3. Использование библиотеки в консольном варианте приложения Выделены изменения в программе с комментариями. program top_down (dat, res); {$APPTYPE CONSOLE} uses SysUtils; const nmax=50; mmax=50; type arrb=array[1..nmax] of integer; arra=array[1..mmax,1..nmax] of integer; var n,m, maxmin, i, j :integer; b:arrb; a: arra; nver, mver, bver, aver :boolean; {результаты анализа данных} dat,res:text; resvar:byte; {вариант решения} {проверка массива b: процедура загружается из библиотеки TopDownDLL.dll} procedure provb(n:integer; var b:arrb; var bver:Boolean; var res:text); external 'TopDownDLL.dll'; {проверка массива a: процедура загружается из библиотеки TopDownDLL.dll} procedure prova(m, n:integer; var a:arra; var aver:Boolean; var res:text); external 'TopDownDLL.dll'; { Решение задачи с фиксацией варианта решения } procedure reshenie (n,m :integer; var b:arrb; var a:arra; var maxmin: integer; var resvar: byte); external 'TopDownDLL.dll'; begin { TODO -oUser -cConsole Main : Insert code here } assign (dat,paramstr(1)); reset(dat); assign (res,paramstr(2)); rewrite(res); {вывод по обр1} writeln(res,' Задача top_down. Обработка матрицы '); {ввод, анализ, входных данных} {проверка n} readln(dat,n); writeln(res,' Исходный массив b из ', n:2, ' элементов:'); { ввод- вывод n } nver:=true; if (n<=0) or (n>=50) then {n неверно} begin nver:=false; writeln(res,' n задано неверно '); {вывод по обр 4.1} end; if nver {n верно} then begin for i:=1 to n do { ввод(b(i),i=1,n) } read(dat,b[i]); for i:=1 to n do { вывод(b(i),i=1,n) по<
span> обр 2.2 } write(res,' ',b[i]:3); writeln(res); { А0.1. проверка массива b} {вх.:n,b; вых.:bver} provb(n,b,bver,res); end; if (nver and bver) then {предыдущие данные верны} begin {ввод(m); вывод(m,n)по обр 2.3} readln(dat,m); writeln(res,' Исходная матрица ', m:2, ' х', n:2, ': '); {проверка m} mver:=true; if (m<=0) or (m>50) then {m неверно} begin mver:=false; writeln(res,' m задано неверно '); {вывод по обр 4.3} end; end; if (nver and bver and mver) then{предыдущие данные верны} begin { ввод((a(i,j),j=1,n),i=1,m); вывод((a(i,j),j=1,n),i=1,m)по обр 2.4; } for i:=1 to m do begin for j:=1 to n do read(dat, a[i,j]); readln(dat); end; for i:=1 to m do begin for j:=1 to n do write (res,' ',a[i,j]:3); writeln(res); end; {А0.2. проверка массива а} {вх.:m,n,a; вых.: aver} prova(m,n,a,aver,res); end; if (nver and mver and bver and aver) then {все данные верны} begin {A0.3a Решение задачи с фиксацией варианта решения} reshenie (n,m, b, a, maxmin, resvar); writeln (res, ' Результаты'); {A0.3b Анализ варианта решения и вывод по соответствующему образцу} {Заглушки} case resvar of 1: writeln (res, ' Измененная матрица'); 2: writeln (res, ' Максимальное значение минимумов строк матрицы'); 3: writeln (res, ' Матрица не меняется');<
span> end; end else {хотя бы одно данное неверно} writeln(res,' Задача не решалась'); { вывод по обр.4.5; } close(dat); close(res); end. 2.4. Использование библиотеки в варианте с графическим интерфейсом Приводится только часть модуля, вызывающего процедуру решения. unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids, Spin;const nmax=50; mmax=50;type TForm1 = class(TForm) SpinEdit1: TSpinEdit; // n - число элементов массива b и столбцов матрицы a StringGrid1: TStringGrid; //таблица для ввода массива b SpinEdit2: TSpinEdit; // m - число строк матрицы a StringGrid2: TStringGrid; //таблица для ввода матрицы a Label1: TLabel; //Заголовок "Число n элементов массива B:" Label2: TLabel; //Заголовок "Исходный массив B из n элементов:" Label3: TLabel; //Заголовок "Число m строк матрицы A" Label4: TLabel; //Заголовок "Исходная матрица A m x n" Label5: TLabel; //Заголовок "Задача top_down. Обработка матрицы" Label6: TLabel; //Сообщение "Число элементов задано неверно!" Label7: TLabel; //Сообщения об ошибочных элементах массива B Button1: TButton; //Кнопка "Решить" procedure SpinEdit1Change(Sender: TObject); procedure SpinEdit1Exit(Sender: TObject); procedure StringGrid1Exit(Sender: TObject); procedure SpinEdit2Exit(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; arrb=array[1..nmax] of integer; arra=array[1..mmax,1..nmax] of integer; var Form1: TForm1; //Форма для ввода и анализа входных данных implementation uses Unit2; // Unit2 содержит форму для вывода результатов {$R *.dfm} procedure reshenie (n,m :integer; var b:arrb; var a:arra; var maxmin: integer; var resvar: byte);external 'TopDownDLL.dll'; //Ввод и проверка n с выводом сообщения при наличии ошибки procedure TForm1.SpinEdit1Change(Sender: TObject);begin ........ end; //Формирование таблицы для ввода массива b и столбцов таблицы для ввода матрицы aprocedure TForm1.SpinEdit1Exit(Sender: TObject); var i:integer;begin ....... end; //Проверка элементов массива b при передаче фокуса ввода следующему компоненту procedure TForm1.StringGrid1Exit(Sender: TObject); var i:byte; begin ........ end; //Формирование таблицы для ввода матрицы a procedure TForm1.SpinEdit2Exit(Sender: TObject); var i,j:integer;begin ............... end; //Решениеprocedure TForm1.Button1Click(Sender: TObject); var n,m, maxmin, i, j :integer; b: arrb; a: arra; resvar: byte; begin if label7.Visible=false then begin //Вывод входных данных в выходную форму Form2 ......................... //Преобразование входных данных из строк в числа ............................. //Решение задачи с выводом результатов в Form2 {A0.3a Решение задачи с фиксацией варианта решения} reshenie (n,m, b, a, maxmin, resvar); {A0.3b Анализ варианта и вывод п соотаветствующему образцу} case resvar of 1: Form2.label4.visible:=true; //writeln (res, ' Измененная матрица'); //2: writeln (res, ' Максимальное значение минимумов строк матрицы'); //3: writeln (res, ' Матрица не меняется'); end; Form2.Visible:=true; Form1.Visible:=false; end; end; end. |