Скачать 1.17 Mb.
|
Рис.A: Пример с TShape Во втором примере (проект PIXELS.DPR, рис.2) показано, как осуществить доступ к отдельной точке на изображении (на канве). По нажатию кнопки "Fill" всем точкам изображения присваивается свой цвет: procedure TForm1.Button1Click(Sender: TObject); var i, j : Longint; begin Button1.Enabled:=False; with Canvas do for i:=1 to Width do begin Application.ProcessMessages; for j:=1 to Height do Pixels[i,j]:=i*j; end; Button1.Enabled:=True; end; Рис.B: Работа с точками на канве. В третьей программе (проект DRAW.DPR, рис.3) приведен пример использования методов, выводящих изображение - Draw и StretchDraw: Рис.C: Вывод изображений на канву. Прорисовка изображений происходит в обработчике события OnPaint для формы: procedure TForm1.FormPaint(Sender: TObject); begin with Canvas do begin Draw(0,0, Image1.Picture.BitMap); StretchDraw(Rect(250,0,350,50),Image1.Picture.BitMap) end; end; 2.2 Структурное и модульное программирование в Delphi Подпрограмму можно определить как относительно самостоятельный фрагмент программы, оформленный таким образом, чтоего можно выполнять многократно, передавая ему управление из разных частей программы для обработки разных данных.Использование подпрограмм позволяет уменьшить размер про-граммы (если в различных частях программы необходимо выполнять обработку данных по одному алгоритму) и сделать ее исход-ный текст более удобным для понимания процесса обработки дан-ных (если алгоритм подпрограммы обладает функциональной законченностью, а имя подпрограммы отражает ее назначение, как,например, у стандартных подпрограмм Sin(X) или Abs(X)). Пре-имущества использования подпрограмм проявляются также приразработке больших программ, так как становится возможным распараллелить процесс создания программного продукта, поручив разработку отдельных подпрограмм разным исполнителям, и, что более важно, . упростить процесс написания и отладки. Разбиение программы на подпрограммы производится прежде всего по функциональному признаку: подпрограмма должна реализовывать одну, но законченную функцию. При этом надо стремиться к сокращению количества межпрограммных связей (количеству передаваемых параметров). Рекомендуемый размер подпрограммы составляет 10.60 строк текста. Нецелесообразно создавать слишком короткие подпрограммы, а размещение подпрограммы в пределах одной страницы позволит программисту охватить весь текст одним взглядом и не тратить время на переключение внимания с одной страницы на другую. В языке Object Pascal используются два вида подпрограмм . функции и процедуры. При общих принципах оформления функции обладают дополнительными возможностями. Поэтому сна- чала рассмотрим объявление и использование процедур, а затем особенности функций. Процедуры. При работе с подпрограммами следует различать термины объявление подпрограммы (описание подпрограммы) и обращение к подпрограмме (вызов подпрограммы). Объявление подпрограммы содержит ее имя и описывает процесс обработки данных, представленных параметрами (пока будем считать так, следуя рекомендациям структурного программирования). В объявлении подпрограммы параметры называют формальными. Имя подпрограммы задает ее разработчик, и оно должно быть уникальным в своем блоке. Обращение к подпрограмме выполняется по ее имени и описывает данные (фактические параметры), обработку которых она должна выполнить. Выполнение обращения приводит к передаче управления подпрограмме. Вызовов одной подпрограммы может быть несколько, а фактические параметры в них . разными. Объявления подпрограмм и их вызовы должны оформляться в соответствии с правилами, которые будут представлены в виде синтаксических диаграмм. Имя процедуры (рис. 6.1) строится так же, как и прочие имена в языке Object Pascal. Блок процедуры, как и блок основной программы, может содержать объявления меток, констант, типов, переменных, подпрограмм и обязательно . составной оператор (begin .... end), представляющий алгоритм. Список формальных параметров содержит имена, используемые в теле подпрограммы для описания процесса обработки данных. Обращение к процедуре является отдельным оператором программы. Список фактических параметров представляет реально существующие данные. Соответствие фактических параметров формальным устанавливается порядком их следования в списках. При вызове подпрограммы фактические параметры как бы занимают в алгоритме места соответствующих формальных (уточнение будет дано позже), после чего алгоритм выполняется. Пример объявления и вызова процедуры, выводящей на экран первое из двух значений, представленных параметрами, кратное 5, или сообщение, что кратных нет: //Объявление процедуры procedure PutMod5(I,J:Integer); // I и J . формальные параметры begin if I mod 5 = 0 then WriteLn(I) else if J mod 5 = 0 then WriteLn(J) else WriteLn('Нет параметров, кратных 5'); end; . . . . . begin // РАЗДЕЛ ОПЕРАТОРОВ ПРОГРАММЫ . . . . . //Вызов процедуры PutMod5(A+3, B);//A+3 и B . фактические параметры . . . . . end. Рассмотрим на конкретных значениях переменных A и B, что будет выведено подпрограммой: при A = 2 и B = 10 будет выведено значение 5; при A = 3 и B = 10 будет выведено значение 10; при A = 3 и B = 11 будет выведен текст «Нет параметров, крат- ных 5». Тип в объявлении формального параметра пока будем считать обязательным и задавать только именем ранее объявленного или стандартного типа (другие возможности будут рассмотре- ны позже).Прежде чем перейти к пояснению правил объявления формальных параметров, введем в рассмотрение два термина: входной параметр и выходной параметр. Параметр считается входным, если он представляет исходные данные для счета по алгоритму подпрограммы (в рассмотренном примере оба параметра являются входными). Параметр считается выходным, если он представляет результаты счета по подпрограмме. Допускается, что один и тот же параметр может одновременно представлять и исходные данные, и результат, т. е. быть одновременно и входным, и выходным. В языке Object Pascal рассмотренное функциональное деление параметров (на входные, выходные, входные-выходные) дополнено механизмами реализации их функций, отраженными в правилах объявления формальных параметров. Сначала рассмотрим два вида объявлений параметров: параметры-значения и параметры-переменные.Параметры-значения всегда являются только входными параметрами. Соответствующими фактическими параметрами могут быть выражения (в частности, константы и переменные). При вызове подпрограммы выражения вычисляются и полученные значения заносятся (а значения констант и переменных просто копируются) в ячейки памяти, представленные соответствующими формальными параметрами, значения которых внутри подпрограммы можно изменять. Механизм параметров-значений таков, что эти изменения никак не отразятся на значениях фактических параметров, т. е. после выхода из подпрограммы они останутся неизменными. Таким образом, формальный параметр-значение можно рассматривать как переменную, известную внутри подпрограммы,а механизм таких параметров . как защиту фактических параметров, если они переменные, от непреднамеренного изменения.Объявление параметров-значений дается просто их именем (списком имен через запятую) и типом (без предшествующих слов var, const, out). В рассмотренной процедуре PutMod5 оба параметра представляют собой параметры-значения. Параметры-переменные являются одновременно и входными, и выходными параметрами. Соответствующими фактическими параметрами могут быть только переменные. Механизм параметров-переменных таков, что изменения, выполняемые в алгоритме подпрограммы над соответствующими формальными параметрами, приводят к изменению значений фактических, и эти изменения сохранятся после выхода из подпрограммы. Достигается это за счет того, что в подпрограмму передается не сама переменная, а ссылка на нее, т. е. обеспечивается непосредственный доступ из подпрограммы к данным фактического параметра. Объявление параметров-переменных дается с предшествующим их имени (списку имен) словом var и типом. Пример процедуры, умножающей данные в первых n ячейках массива Mas на дробную часть числа R (все участвующие в обработке данные должны передаваться через параметры): type tMas=array[1..8] of Real; . . . . . //Объявление процедуры procedure MasMulR(R:Real; N:Integer; var Mas:tMas); var i:Integer; begin R:=Frac(R);//Получить дробную часть R for i:=1 to N do Mas[i]:=Mas[i]*R; end;//MasMulR . конец текста процедуры . . . . . var X:tMas=(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0); Z:Real=3.4; . . . . . begin // РАЗДЕЛ ОПЕРАТОРОВ ПРОГРАММЫ . . . . . MasMulR(Z,5,X);//Вызов процедуры . . . . . end. В этом примере Mas является и входным, и выходным, поэтому он объявлен как параметр-переменная (с предшествующим словом var). Параметр R . только входной. Так как он объявлен как параметр-значение, то его после использования в качестве входного данного можно менять внутри подпрограммы, т. е. ис пользовать как дополнительную переменную, не опасаясь, что изменится значение соответствующего фактического параметра. При указанных в примере начальных значениях переменных после выполнения процедуры переменная Z сохранит свое значение 3.4, а в массиве будут следующие данные: 0.4, 0.8, 1.2, 1.6, 2.0, 6.0, 7.0, 8.0. Параметры-значения обладают одним недостатком, который может оказаться очень существенным, если параметром является структурная переменная, занимающая большой объем памяти, например, массив. В этом случае подпрограмма, получив управление, должна выделить такой же объем памяти, как фактический параметр, и скопировать в нее данные из фактического параметра. Таким образом, недостаток заключается в том, что нерационально используется память и происходит потеря времени на копирование данных перед началом их обработки по алгоритму подпрограммы. Указанных недостатков лишен другой вид входного параметра, получивший название «параметр-константа». Параметр-константа, как и параметр-значение, служит для представления только входных данных. При его использовании в подпрограмму передается ссылка на фактический параметр (как и для параметра-переменной), но для исключения непреднамеренного изменения во время работы программы уже на этапе компиляции выполняют соответствующие проверки. Исполняемая программа не создается, если подпрограмма содержит операторы, которые могут изменить данные фактического параметра. Объявление параметров-констант дается с предшествующим их имени (списку имен) словом const и типом. Последний вид параметра следует использовать для параметров, представляющих только результаты работы подпрограммы. По аналогии с параметрами других видов ему подошло бы название параметр-результат или по предшествующему его име- ни слову out в объявлении . параметр-выходная переменная. Этот параметр передается по ссылке, но компилятор не запрещает его использование в качестве источника исходных данных. За этим должен следить программист, а слово out перед именем в списке формальных параметров призвано облегчить понимание алгоритма подпрограммы, напоминая, что параметр не представляет входных данных. Пример процедуры, в объявлении которой желательно использовать параметр-константу и параметр-результат. Подпрограмма должна вычислять сумму положительных элементов массива X(100, 100) и их количество: type tMas=array[1..100,1..100] of Extended; . . . . . //Объявление процедуры procedure SumCol(const X:tMas, out S: Extended; out K:Integer); var i,j: Integer; begin S:=0; K:=0; for i:=1 to 100 do for j:=1 to 100 do if X[i,j]>0 then begin S:=S+X[i,j]; K:=K+1; end; end; . . . . . var Y:tMas; Sum: Extended; Col: Integer; . . . . . begin // РАЗДЕЛ ОПЕРАТОРОВ ПРОГРАММЫ . . . . . SumCol(Y,Sum,Col); . . . . . end. Взглянув на заголовок подпрограммы, сразу можно сказать, что первый параметр является только входным, а два последних. только выходными. Первый параметр объявлен параметром-кон- стантой, а не параметром-значением, чтобы избежать выделения памяти в 100 000 байт и копирования в нее данных из фактического параметра . массива Y. 6.2. Пример выполнения задания Составить процедуру, копирующую из матрицы A(m, n), m Ј 10, n Ј 14 положительные элементы в массив Pol и подсчитывающую их количество kPol, а отрицательные элементы . в массив Otr и подсчитывающую их количество kOtr. Использовать эту процедуру для матрицы В в основной программе. Если окажется, что положительных и/или отрицательных элементов в матрице нет, то вывести соответствующие сообщения, иначе скопированные в массивы данные: program Project1; {$APPTYPE CONSOLE} uses SysUtils; const mMax=10; nMax=14; 179 type tMatr=array[1.. mMax,1.. nMax] of Real; tMas=array[1.. mMax * nMax] of Real; procedure PolOtr(const A:tMatr; m,n:Integer; out Pol, Otr:tMas; out kPol, kOtr:Integer); var i,j:Integer; begin kPol:=0; kOtr:=0; for i:=1 to m do for j:=1 to n do begin if A[i,j]>0 then begin kPol:= kPol +1; Pol[kPol]:=A[i,j]; end else if A[i,j]<0 then begin kOtr:= kOtr +1; Otr[kOtr]:=A[i,j]; end; end; end; var B:tMatr; P,O:tMas; m,n,i,j,kP,kO:Integer; begin // РАЗДЕЛ ОПЕРАТОРОВ ПРОГРАММЫ WriteLn('Введите количество строк и столбцов'); ReadLn(m,n); WriteLn('Введите матрицу по строкам'); for i:=1 to m do begin for j:=1 to n do Read(B[i,j]); 6 ReadLn; end; PolOtr(B,m,n,P,O,kP,kO); if kP>0 then begin WriteLn(' Массив положительных'); for i:=1 to kP do Write(P[i]:6:1,' '); end else WriteLn('Положительных элементов нет'); WriteLn; if kO>0 then begin WriteLn(' Массив отрицательных'); for i:=1 to kO do Write(O[i]:6:1,' '); end else WriteLn('Отрицательных элементов нет'); ReadLn; end. Функции. Отличие функции от процедуры состоит в том, что: в заголовке после списка параметров необходимо указать тип функции (т. е. тип вычисляемого ею результата) . имя ранее объявленного или стандартного типа; . в вызывающей программе обращение к функции можно записывать в правой части оператора присваивания и в выражениях, если тип результата простой (но присваивать значение имени функции в вызывающей программе запрещено); . в объявлении функции ее имя (не обращение, делающее подпрограмму рекурсивной) не должно встречаться в правой части операторов присваивания или в выражениях; . в объявлении функции должен быть хотя бы один оператор, присваивающий ее имени или объявленной по умолчанию локальной (известной только внутри функции) переменной Result того же типа, что и тип функции, результат вычислений; . в отличие от имени переменную Result можно использовать в правых частях операторов присваивания и в выражениях как дополнительную переменную, представляющую результат вычислений. Обращение к функции, как и к процедуре, можно записывать как отдельный оператор в режиме расширенного синтаксиса, используемом в Delphi по умолчанию. Обращение к функции отдельным оператором имеет смысл, когда интересующий нас результат представлен параметрами, а не именем функции. Отключить режим расширенного синтаксиса можно директивой {$X-} или {$EXTENDEDSYNTAX OFF}, но тогда не будет объявлена по умолчанию локальная переменная Result и при попытке ее использования компилятор сообщит об ошибке. Пример 1. Составить и использовать функцию, возвращающую максимальный из первых N элементов массива X(N), N Ј 100: type tMas=array[1..100] of Real; . . . . . function MaxMas(N:Integer; const X:tMas):Real; var i:Integer; begin Result:=X[1]; for i:=2 to N do if X[i]>Result then Result:=X[i]; end; . . . . . var Y:tMas; begin // РАЗДЕЛ ОПЕРАТОРОВ ПРОГРАММЫ . . . . . //Вызов функции в операторе вывода WriteLn('Максимальный из сорока ' ,'элементов массива Y = ' ,MaxMas(40, Y)); . . . . . end. Если отключить режим расширенного синтаксиса, то в объявлении функции пришлось бы отказаться от использования переменной Result и объявить дополнительную переменную для поиска максимального значения в массиве. В результате получили бы следующее объявление функции: function MaxMas(N:Integer; const X:tMas):Real; var i:Integer; R:Real;//Дополнительная переменная begin R:=X[1]; for i:=2 to N do if X[i]>R then R:=X[i]; //Чтобы функция возвратила вычисленное значение, //оно должно быть присвоено ее имени MaxMas:=R; end; Использование функций позволяет не только сделать текст программы более удобным для понимания алгоритма, но и уменьшить его при необходимости повторных вычислений в разных частях программы. Приложение Delphi помимо стандартных модулей может использовать модули, создаваемые пользователями. Каждый модуль пользователя является отдельно подготовленной и хранящейся в отдельном файле с расширением .pas программной единицей, которая может быть использована любой программой. В Delphi реализован модульный принцип программирования, причем модули играют роль наборов заранее подготовленных и отлаженных подпрограмм, именованных констант, типов, переменных, которые могут использоваться в тех частях программы (в основной программе и модулях). Модули также могут содержать код, выполняемый до передачи управления в указанные части программы, и код, выполняемый после возврата управления из них. Любая часть модуля может быть пустой, однако ключевые слова interface и implementation опускать нельзя. Если в модуле не требуются части инициализации и финализации, то не нужно записывать слова initialization и finalization, но если часть финализации необходима, то должна присутствовать и часть инициализации, даже если в ней нет ни одного оператора. В интерфейсной части объявляют только те имена, которые могут использоваться в основной программе или в модуле, к которому подключен данный модуль, причем именованные константы, типы и переменные объявляют как обычно, а процедуры и функции . своими заголовками. Эти имена будут известны и в остальных частях модуля. Полное объявление подпрограмм, заголовки которых представлены в интерфейсной части, должно располагаться в части реализации. Кроме них в части реализации могут объявляться другие подпрограммы, метки, а также, в дополнение к объявлениям в интерфейсной части, именованные константы, типы и переменные, недоступные вне модуля. Они могут иметь вспомогательное значение при реализации подпрограмм интерфейсной части или использоваться в частях инициализации и финализации. Часть инициализации предназначена для размещения операторов, выполнение которых предшествует выполнению операторов основной программы (той части программы, которая ис- пользует данный модуль), а часть финализации . для операторов, выполняемых после окончания основной (указанной части) программы. Например, в части инициализации можно создать временные файлы для хранения данных только во время выполнения программы, а в части финализации удалить эти файлы. Такое решение позволит упростить разработку программы и избежать засорения дискового пространства ненужными файлами при возникновении исключений в основной программе, так как часть финализации будет выполнена в любом случае. Например, если модуль Unit1, в котором создается файл 'TempFile.txt': unit Unit1; interface var //Файловая переменная f будет представлять //временный файл в программе, //использующей данный модуль f: TextFile; implementation initialization //Связать файловую переменную f //с внешним именем файла 'TempFile.txt' Assign(f, 'TempFile.txt'); Rewrite(f); //создать файл finalization if FileExists('TempFile.txt') then //Если файл не был уничтожен, begin //то try CloseFile(f); //Закрыть файл except //Сообщения не будет, //если файл был закрыт в основной программе end; Erase(f); //Уничтожить закрытый файл end end. . присоединить к программе Project1: program Project1; {$APPTYPE CONSOLE} uses SysUtils, Unit1;//Использовать модуль Unit1 в этой программе . . . . . . . то файл 'TempFile.txt' будет создан до передачи управления в основную программу и с ним можно будет работать, используя файловую переменную f (открывать, закрывать, открывать для до- бавления текста, записывать текст в файл, читать из файла, уничтожать файл), а после выхода из основной программы при любом ее завершении (нормальном или аварийном) управление будет передано операторам части финализации модуля Unit1, и файл 'TempFile.txt' будет уничтожен. Объявления в отдельных частях модуля могут располагаться в любой последовательности и чередоваться при соблюдении правила использования имен: при объявлении нового имени (констан- ты, типа, переменной, процедуры, функции) могут использоваться только ранее объявленные имена или имена из подключенных модулей. Компилятор узнает о подключенных модулях, анализируя предложения использования в основной программе или в самих модулях. Предложение использования строится из ключевого слова uses и следующего за ним списка имен подключаемых модулей. В основной программе и в интерфейсной части модуля формы, создаваемых в среде Delphi, предложения использования вставляются автоматически . имена новых модулей следует просто добавить в уже имеющийся список. При создании нового модуля пользователь при необходимости должен сам добавить предложения использования. Например, в модуль, создаваемый для решения вычислительных задач, следует в интерфейсную часть или в часть реализации включить предложение использования со стандартным модулем Math: uses Math; Присутствие имени модуля в предложении использования основной программы (или другого модуля) означает, что объявленные в его интерфейсной части константы, типы, переменные и подпрограммы доступны для использования. Существует отличие в назначении предложений использования в разных частях модуля. Предложения использования в интерфейсных частях должны строиться так, чтобы не возникало взаимных ссылок модулей непосредственно или через другие модули. Только в этом случае компилятор сможет определить порядок использования объявлений из интерфейсных частей.Для части реализации такого ограничения нет. Это позволяет строить взаимно рекурсивные подпрограммы, принадлежащие разным модулям. Можно использовать взаимную рекурсию и внут- ри модуля без применения директивы forward, так как оно действует в модулях по умолчанию для всех подпрограмм, заголовки которых размещены в интерфейсной части. При разработке программы в среде Delphi вновь создаваемый модуль (по команде File/New/Unit) добавляется в предложение использования основной программы автоматически. Также автоматически добавляется в предложение использования основной программы ссылка на готовый модуль. Для этого следует ввести команду Project/Add to Project..., в диалоге выбрать папку с модулем и в ней . сам модуль с расширением .pas (при разработке приложения с формой текст основной программы можно отобразить командой Project/View Source). После добавления в проект модулей программист уже в них должен прописать в предложениях использования взаимные ссылки. В приложениях с формой убедиться, что модуль подключен, можно, отобразив текст основной программы командой Project/View Source, где должна быть ссылка на модуль в предложении uses, или открыв окно диалога Project Manager командой View/Project Manager... Пример 1. Составить консольное приложение, выполняющее обработку матриц по формуле (A + B) ЧC + D. Приложение должно использовать модули Unit1 и Unit2, подготовленные в проекте и хранящиеся в одной папке с основной программой. Модуль Unit1 предназначен для объявления типа массивов, которые будут хранить матрицы, участвующие в вычислениях, и две процедуры: ReadMatr ввода матрицы и WriteMatr вывода. Модуль Unit2 также должен содержать процедуры AddMatr сложения матриц и MulMatr умножения. Требования к модулю Unit1. Для хранения матриц следует использовать двумерные динамические массивы. Первый параметр процедуры ReadMatr должен представлять матрицу, размеры которой заданы вторым и третьим параметрами, а четвертый параметр целого типа с начальным значением 0 указывать режим работы процедуры. Процедура ReadMatr должна обеспечить ввод матрицы с клавиатуры в виде матрицы по строкам, если четвертый параметр при ее вызове опущен. Этот параметр предназначен для отладки программ, использующих модуль Unit1. При задании в вызове процедуры ReadMatr четвертого параметра, не равного 0, процедура должна генерировать матрицу случайных чисел от нуля до абсолютного значения этого параметра включительно, причем если он меньше нуля, то при многократных запусках программы генерироваться должны разные данные, ина- че . одни и те же. Сгенерированные матрицы следует выводить в виде матрицы по строкам. роцедура WriteMatr должна иметь один параметр, представляющий матрицу, и обеспечивать ее вывод в виде матрицы по строкам с пробелом между числами не менее одного. Требования к модулю Unit2. Для хранения матриц следует использовать двумерные динамические массивы типа, объявленного в модуле Unit1. В процедурах AddMatr и MulMatr два первых параметра должны представлять только входные данные (матрицы, представляющие только исходные данные), а третий . только выходные данные (результирующую матрицу). Требования к основной программе. Использовать условную ком- пиляцию, обеспечивающую при объявлении имени Debug директивой {$IFDEF Debug} генерацию случайных чисел для матриц, представляющих исходные данные, иначе ввод матриц с кла- виатуры. //Модуль Unit1 объявления типа двумерного //динамического массива //и процедур ввода и вывода матриц. unit Unit1; interface uses Math; type tm1=array of Integer; //тип двумерного динамического массива tm2=array of tm1; procedure ReadMatr(out x:tm2; m,n:Integer; r:Integer=0); procedure WriteMatr(const x:tm2); implementation procedure ReadMatr(out x:tm2; m,n:Integer; r:Integer=0); {Ввод матрицы m*n по строкам в динамический массив типа tm2: при r=0 - ввод с клавиатуры, иначе - от датчика случайных чисел, причем при r>0 - без Randomize, иначе - с Randomize} var i,j:Integer; begin //Установить размеры массива x //равными размерам вводимой матрицы SetLength(x,m,n); if r=0 then begin //Ввод матрицы с клавиатуры for i:=0 to m-1 do begin for j:=0 to n-1 do Read (x[i,j]); ReadLn end; end 231 else begin //Генерация матрицы случайных целых чисел, //из интервала 0..r+1 if r<0 then //При r<0 будет создан //новый набор случайных чисел для матрицы Randomize; r:=Abs(r)+1; for i:=0 to m-1 do for j:=0 to n-1 do x[i,j]:=Random(r); WriteMatr(x); end; end;//ReadMatr procedure WriteMatr(const x:tm2); {Вывод матрицы m*n по строкам из динамического массива} var i,j,m,n,xmax:Integer; begin m:=High(x); n:=High(x[0]); xmax:=Abs(x[1,1]); for i:=0 to m do for j:=0 to n do if Abs(x[i,j])>xmax then xmax:=Abs(x[i,j]); for i:=0 to m do begin for j:=0 to n do Write (x[i,j]:Trunc(Log10(xmax))+2); WriteLn; end; end;//WriteMatr end. //Модуль Unit2 объявления процедур //сложения и умножения матриц unit Unit2; interface uses Unit1; {Фактические параметры обеих процедур не могут быть одновременно и входными, и выходными} procedure AddMatr(const x,y:tm2; out z:tm2); 7. МОДУЛИ ПОЛЬЗОВАТЕЛЕЙ 232 ПРАКТИКУМ ПО ПРОГРАММИРОВАНИЮ procedure MulMatr(const x,y:tm2; out z:tm2); implementation procedure AddMatr(const x,y:tm2; out z:tm2); {Процедура сложения матриц Z=X+Y} var i,j,m,n:Integer; begin m:=High(x); //m+1 - число строк в X, Y и Z n:=High(x[0]);//n+1 - число столбцов в X, Y и Z //Установить размеры массива z //равными размерам матрицы Z SetLength(z,m+1,n+1); for i:=0 to m do for j:=0 to n do z[i,j]:=y[i,j]+x[i,j]; end;//AddMatr procedure MulMatr(const x,y:tm2; out z:tm2); {Процедура умножения матриц Z=X*Y} var i,j,m,n,l,k:Integer; begin // m+1 - число строк в X и Z столбцов в Y m:=High(x); // n+1 - число столбцов в X n:=High(x[0]); // l+1 - число столбцов в Y l:=High(y[0]); //Установить размеры массива z //равными размерам матрицы Z SetLength(z,m+1,l+1); for i:=0 to m do for j:=0 to l do begin z[i,j]:=0; for k:=0 to n do z[i,j]:=z[i,j]+x[i,k]*y[k,j]; end; end;//MulMatr end. //Основная программа вычисления матрицы E=(A+B)*C+D program Project1; {$APPTYPE CONSOLE} 233 uses SysUtils, Unit1 in 'Unit1.pas', Unit2 in 'Unit2.pas'; //Объявление имени Debug, //используемого при условной компиляции. {$DEFINE Debug} //Отменить объявление имени Debug можно, //удалив строку с директивой {$DEFINE Debug} //или превратив ее в комментарий: //{$DEFINE Debug}. var a,b,c,d,e,f,g:tm2; begin {$IFDEF Debug} //Если имя Debug объявлено директивой //{$DEFINE Debug}, то в исполняемую программу //будут включены следующие операторы, обеспечивающие //генерацию матриц случайных чисел и их вывод WriteLn(' Mатрица A 2х3 целых случайных чисел ' ,'в диапазоне 0..7'); ReadMatr(a,2,3,8); WriteLn(' Mатрица B 2х3 целых случайных чисел ' ,'в диапазоне 0..5'); ReadMatr(b,2,3,6); WriteLn(' Mатрица C 3х4 целых случайных чисел ' ,'в диапазоне 0..8'); ReadMatr(c,3,4,-9); WriteLn(' Mатрица D 2х4 целых случайных чисел ' ,'в диапазоне 0..8'); ReadMatr(d,2,4,9); {$ELSE} //иначе, то есть если имя Debug //не объявлено, то в исполняемую программу //будут включены следующие операторы, //обеспечивающие ввод матриц с клавиатуры. WriteLn(' Введите матрицу A 2х3'); ReadMatr(a,2,3); WriteLn(' Введите матрицу B 2х3'); ReadMatr(b,2,3); WriteLn(' Введите матрицу C 3х4'); ReadMatr(c,3,4); WriteLn(' Введите матрицу D 2х4'); ReadMatr(d,2,4); {$ENDIF} 7. МОДУЛИ ПОЛЬЗОВАТЕЛЕЙ 234 ПРАКТИКУМ ПО ПРОГРАММИРОВАНИЮ Рис. 7.2 //Вычисление и вывод матриц AddMatr(a,b,f); WriteLn(' Mатрица F=(A+B)'); WriteMatr(f); MulMatr(f,c,g); WriteLn(' Mатрица G=(A+B)xC'); WriteMatr(g); AddMatr(g,d,e); WriteLn(' Mатрица E=(A+B)xC+D'); WriteMatr(e); ReadLn; end. При запуске программы с директивой, объявляющей имя Debug, в окно программы сразу будут выведены результаты построения матриц случайных чисел с поясняющими текстами и вычисления (A + B)ЧC + D по шагам, как показано на рис. 7.2. При повторных запусках программы матрицы A и B не изменятся, а C и D будут создаваться всякий раз новые, так как генерация новых случайных чисел стандартной функцией Random начинается с вызова ReadMatr(c,3,4,-9) для построения матрицы C, где отрицательное значение последнего параметра требует выполнения процедуры Randomize. После отладки программы строку с директивой {$DEFINE Debug} следует превратить в комментарий. К Unit1 должен подключаться стандартный модуль Math, так как в процедуре WriteMatr используется стандартная процедура Log10, но поскольку объявления интерфейсной части Unit1 не требуют подключения Math, то предложение использования uses Math; размещено в его части реализации. Модуль Unit1 должен быть под ключен к Unit2 в интерфейсной части, так как объявленный в Unit1 тип tm2 двумерного динамического массива используется при объявлении заголов- ков процедур AddMatr и MulMatr. Следует обратить внимание на одну особенность динамичес- ких массивов при работе с матрицами, использованную в процедурах WriteMatr, AddMatr и MulMatr, . размеры массивов всегда совпадают с размерами матриц, что исключает необходимость указания их в качестве параметров подпрограмм. В соответствии с условиями примера 1 входные параметры объявлены как const-параметры, а выходные . как out-параметры. При наличии в разных модулях одинаковых имен, объявленных в их интерфейсных частях, использование их подчиняетсяследующему правилу: для избежания ошибок перед именем в ка- честве префикса следует использовать имя модуля, если оно использовано без префикса, то будет отнесено к модулю, указанному в предложении использования последним, где это имя было объяв- лено. Так, в основной программе последним в предложении использования был модуль Unit3, поэтому вызовы его процедурыMulMatr записаны без префиксов (например, MulMatr(a,b,b)), а вызовы процедур модуля Unit2 . с префиксом (например,Unit2.MulMatr(a,d,c)). 2.3. Объектно-ориентированный подход к проектированию прикладных программ Объектно-ориентированное программирование (ООП) — это технология, основанная на представлении программ в виде совокупности объектов, каждый из которых является реализацией собственного класса, которые в свою очередь образуют иерархию на принципах наследования. Основное достоинство ООП — сокращение количества межмодульных вызовов и уменьшение объемов информации, передаваемой между модулями, по сравнению с модульным программированием. Это достигается посредством более полной локализации данных и интегрирования их с подпрограммами обработки, что позволяет вести практически независимую разработку отдельных частей (объектов) программы. Объектная декомпозиция При использовании технологии ООП решение представляется в виде результата взаимодействия отдельных элементов некоторой системы, имитирующей процессы, происходящие в предметной области поставленной задачи. Каждый элемент системы, получая сообщение, выполняет заранее определенную последовательность действий (например, обрабатывает полученные данные, изменяет свое состояние, пересылает полученные данные другому элементу системы). Передавая сообщения от одного элемента системы к другому, система выполняет поставленную перед ней задачу. Элементы системы, параметры и поведение которой определяются условием задачи, обладающие самостоятельным поведением (т. е. «умеющие» выполнять некоторые действия, зависящие от полученных сообщений и состояния элемента), получили название объектов . Процесс представления предметной области в виде совокупности объектов, обменивающихся сообщениями, называется объектной декомпозицией. Упражнение 1. Выполните объектную декомпозицию программы, которая по запросу пользователя рисует точку, окружность или квадрат. По правилам объектной декомпозиции разрабатывается имитационная модель программы. Для этого необходимо проанализировать все происходящие в системе процессы и выделить элементы, обладающие собственным поведением, воздействующие на другие элементы и/или являющиеся объектами такого воздействия. Основная цель системы — нарисовать фигуру, выбранную пользователем. Действия пользователя — это либо выбор фигуры, либо изменение параметров фигуры (цвет, размер, координаты), либо команда нарисовать выбранную фигуру с заданными параметрами. Для выполнения этих команд можно воспользоваться следующими объектами: Менеджер (получает, анализирует и обрабатывает команды пользователя) и три объекта — фигуры (каждая со своими параметрами). Фигуры получают следующие сообщения: нарисовать, изменить цвет контура, изменить размер, изменить координаты. Все эти сообщения инициируются Менеджером в соответствии с командой пользователя. Получив от пользователя команду Завершить, Менеджер прекращает выполнение программы. В объектно-ориентированном программировании разрабатываемая система состоит из объектов, которые взаимодействуют через передачу сообщений. Каждый объект, получив сообщение, должен определенным образом реагировать на них, выполняя заранее определенные для каждого типа сообщения действия. Например, если объект ОбработатьЗапись будет активизирован, то он должен будет проанализировать, какое именно действие нужно выполнить. Если принято сообщение Редактировать, то объект должен сохранить запись в файл, на место, указанное курсором. Состояние объекта характеризуется набором конкретных значений некоторого перечня всех возможных свойств данного объекта; например, состояние объекта Файл характеризуется значениями «активизирован» — «не активизирован». Это состояние объекта необходимо для выполнения всех действий над записной книжкой: если Файл находится в состоянии «не активизирован», то ни одно сообщение не сможет быть обработано. Набор значений свойств задается на этапе проектирования и не изменяется в процессе функционирования, изменяются лишь конкретные значения. Поведение объектов характеризуется определенным набором реакций на получаемые сообщения и зависит от состояния объекта. Если объект может обладать некоторым состоянием, то, соответственно, может возникнуть необходимость в получении информации об этом состоянии. Для получения такой информации объекту посылается сообщение-запрос. В ответ на запрос объект должен переслать отправителю требуемую информацию. В таких случаях говорят, что над объектом выполнена операция селекции. Обращение к объекту для изменения его состояния возбуждает выполнение операции модификации. Отправитель сообщения-команды, реакцией на которую должна быть модификация объекта, может ожидать завершения операции, а может продолжить выполнение своей программы. Если объект содержит несколько однотипных компонент, например массив чисел, то операция, требующая последовательной обработки этих компонент, называется итерацией. Поэлементно могут выполняться как операции селекции, так и операции модификации. Основные элементы ООП ООП характеризуется четырьмя основополагающими идеями (абстрагирование, инкапсуляция, модульность, иерархия) и тремя дополнительными (типизация, параллелелизм, сохраняемость). Абстрагирование — это один из главных способов решения сложных задач. В результате объектной декомпозиции были выделены объекты. Абстракция предназначена для выделения существенных характеристик каждого объекта, отличающих его от всех других видов объектов и, таким образом, четко определяются его концептуальные границы с точки зрения наблюдателя. Для представления абстракций объектов используется специальный определяемый программистом тип данных — класс. Класс — это структурный тип данных, который включает описание полей данных, а также процедур и функций, работающих с этими полями данных. Процесс объединения данных с действиями над этими данными в единый пакет при наличии специальных правил доступа к элементам пакета получил название инкапсуляция. Итак, сочетание данных с допустимыми действиями над этими данными приводит к «рождению» нового «кирпичика» программирования — класса. Действия — это процедуры и функции, описанные в классе, они получили название методов. Класс представляет собой структуру, динамически размещаемую в памяти. Экземпляр класса называется объектом. Прежде чем программа сможет использовать объект какого-либо класса, его необходимо создать. Объекты создаются и уничтожаются с помощью специальных методов, которые называются constructor (конструктор) и destructor (деструктор). «Рожденный ползать летать не может» — и объект действует только так, как это в нем заложено, и только над тем, что в нем описано. Обращение к данным объекта не через его методы недопустимо. Для корректной работы абстракции доступ к ее внутренней структуре должен быть ограничен. Для этого вводятся две части в описании абстракции. Интерфейс — это совокупность доступных извне элементов реализации абстракции, т. е. основные характеристики состояния и поведения. Реализация — это совокупность недоступных извне элементов реализации абстракции, т. е. внутренняя организация абстракции и механизмы реализации ее поведения. Наличие интерфейса обеспечивает уменьшение возможности «разрушения» (несанкционированного изменения значений полей) объекта извне. При этом сокрытие особенностей реализации упрощает внесение изменений в реализацию класса как в процессе отладки, так и при модификации программы. Таким образом, класс определяет существование глобальной области данных внутри объекта, доступной методам объекта. С другой стороны, доступ к объекту регламентируется и должен выполняться через специальный интерфейс. Для описания нового класса в языке Object Pascal определен следующий синтаксис: Туре <�имя_объявляемого_класса>=с1аss(<�имя_класса_родителя>) Private <�скрытые_элементы_класса> Protected <�защищенные_элементы_класса> Public <�общедоступные_элементы_класса> Published <�опубликованные_элементы_класса> end; Директивы private, protected, public, published предназначены для ограничения доступа к элементам класса. Секция private содержит внутренние элементы, обращение к которым возможно только в пределах модуля, содержащего объявление класса. Секция protected содержит защищенные элементы, которые доступны в пределах модуля, содержащего определение класса, и внутри классов-потомков. Секция public содержит общедоступные элементы, к которым возможно обращение из любой части программы. Секция published содержит опубликованные элементы, которые по ограничению доступа аналогичны public. Для визуальных компонент, (внесенных на панель компонент), информация об элементах, размещенных в этой секции, становится доступной через инспектор объектов. Потомки класса могут менять область доступности всех элементов родительского класса, кроме элементов, объявленных в секции private, так как последние им недоступны. Все объекты Delphi являются динамическими, т. е. размещаемыми в динамической области памяти. Соответственно переменная типа класса по смыслу представляет собой указатель на объект. Вызовы конструктора и деструктора являются обязательными, так как конструктор выполняет размещение объекта в памяти, а деструктор — выгрузку из нее. Упражнение. Разработать класс, переменные которого используются для описания положения геометрической фигуры на экране. Решение Проектируемый класс должен содержать поля для сохранения положения элемента на экране — координаты местоположения х и у, при этом возможными действиями являются инициализация элемента, получение координат, разрушение объекта. Определим класс Position: Для хранения значений координат введем два поля Fx и Fy (в языке Object Pascal принято соглашение названия полей начинать с символа F (от слова Field — поле)). Это внутренние данные класса, чтобы обеспечить их целостность, опишем их в разделе private. Constructor Create предназначен для создания экземпляра класса (объекта), а также для определения начальных значений его полей. Destructor Destroy предназначен для удаления объекта из динамической памяти. Подчеркнем, выделим мысль о том, что согласно идеологии объектно-ориентированного программирования все действия с данными, определенными в классе, осуществляются только путем использования методов объекта. Методы GetX и GetY по запросу обращаются к соответствующему полю объекта и возвращают координаты положения объекта. Итак, объединение данных с действиями над этими данными порождает новый тип, а процесс называется инкапсуляцией. Создавая объекты типа TPosition, инициализируя их в соответствии с условием, получим разные положения на экране, причем параметры будут храниться внутри объектов. Каждая переменная типа class включает набор полей, объявленных в классе. Совокупность значений, содержащихся в этих полях, моделирует конкретное состояние объекта предметной области. Изменение этих значений в процессе работы отражает изменение состояния моделируемого объекта. Воздействие на объект выполняется посредством изменения его полей или вызова его методов. Доступ к полям и методам объекта осуществляется, за исключением специальных случаев, с указанием имени объекта (при этом используются составные имена): <�имя_объекта>.<�имя_поля>; ИЛИ <�имя_объекта>.<�имя_метода>; Все методы объекта обязательно имеют доступ ко всем полям своего объекта. В языке Object Pascal это достигается через неявную передачу в метод специального параметра Self — адреса области данных конкретного объекта. Таким образом, уменьшается количество параметров, явно передаваемых в метод. </0></0></0> |
Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки... Исследовать процессы создания новых технологий и определять их основные тенденции целесообразно, сопоставляя эти технологии с уровнем... |
Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки... Исследовать процессы создания новых технологий и определять их основные тенденции целесообразно, сопоставляя эти технологии с уровнем... |
||
Методические рекомендации по выполнению внеаудиторной самостоятельной... ПМ. 01 Разработка программных модулей программного обеспечения для компьютерных систем |
Конспект лекций Ш 39 Метрология, стандартизация, сертификация: Конспект лекций / О. А. Шейфель; Кемеровский технологический институт пищевой промышленности.... |
||
Конспект лекций для студентов всех форм обучения специальности 080110... Налоги и налогообложение: Конспект лекций / Составитель Н. А. Леончик. – Кемерово, 2006. – 80 с |
Календарно-тематический план учебной дисциплины преподаватель Алексеев Александр Игоревич Наименование междисциплинарного курса мдк. 01. 01 Электрические машины и аппараты |
||
Технические средства автоматизации конспект лекций Конспект лекций предназначен для студентов дневной, вечерней, заочной и дистанционной форм обучения по специальности 220301 «Автоматизация... |
Конспект лекций мдк 02. 02. Электронные средства и методы геодезических измерений ПМ. 02. Выполнение топографических съемок, графического и цифрового оформления их результатов |
||
Конспект лекций Владимир 2010 Министерство образования Российской... Автоматизированные системы бухгалтерского и управленческого учета. Часть 1: Конспект лекций / Владим гос ун-т; Сост.: Д. Н. Васильев... |
Конспект лекций лаконично раскрывает содержание и структуру учебной... Безопасность жизнедеятельности : конспект лекций для студентов очной и заочной форм обучения / сост. В. М. Домашко; Южный федеральный... |
||
Конспект лекций содержание тема Предмет и задачи курса Внутренняя и внешняя среда организации (фирмы) и их взаимосвязь. Мировой рынок и его развитие |
Рабочая программа спецкурса Олимпиадное программирование 8 и класс... Рабочая программа элективного курса «Олимпиадное программирование» для 8 специализированного класса инженерно-технологической направленности... |
||
Рабочая программа междисциплинарного курса мдк 01. 06 «Постановка голоса, хор» ПО) по программам подготовки специалистов среднего звена (далее – ппссз) по специальности 53. 02. 03 Инструментальное исполнительство... |
Рабочая программа междисциплинарного курса «Средства исполнения дизайн-проектов» Рабочая программа междисциплинарного курса «Средства исполнения дизайн-проектов» разработана на основе Федерального государственного... |
||
Конспект лекций по дисциплине для специальности 080101. 65 «Экономическая безопасность» Информационные системы в экономике: конспект лекций по дисциплине для обучающихся по специальности 080101. 65 «Экономическая безопасность»... |
Конспект лекций по дисциплине «Научные основы производства продуктов питания» Конспект лекций по дисциплине «Научные основы производства продуктов питания» для студентов кафедры «Технология и организация общественного... |
Поиск |