ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 17.02.2021
Просмотров: 465
Скачиваний: 1
11
Модули. Структура модуля. Стандартные модули Delphi. 2
Модули. Структура модуля. Стандартные модули Delphi.
Структура модуля.
Модули – одно из ключевых понятий языка Паскаль. Они предназначены для разбиения проекта на части. В каждом модуле могут быть собраны константы, типы, переменные, процедуры и функции, объединенные по смысловому признаку. Например, модуль для работы с комплексными числами или со стеком. Модуль представлен отдельным файлом с расширением *.pas. Скомпилированный модуль имеет расширение *.dcu. Для добавления в проект Delhi нового модуля необходимо выполнить команды File -> New -> Unit. После выполнения этой команды на отдельной закладке редактора кода появляется заготовка модуля:
unit Unit1;
interface
implementation
end.
Модуль по умолчанию будет называться Unit1. Причем, в файл программы в раздел подключения модулей uses будет добавлено соответствующее имя модуля. Это имя будет автоматически изменяться при сохранении модуля под другим именем.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Unit1 in 'Unit1.pas';
begin
end.
Формальная структура модуля выглядит так:
unit <Имя модуля>;
interface
Uses <Имя модуля 1>, <Имя модуля 2>, <Имя модуля 3>;{подключение модулей}
{Раздел описания типов, констант, переменных и заголовков процедур и функций доступных для других модулей и программ}
Const …….
Type …….
Var ……
implementation
Uses <Имя модуля 4>, <Имя модуля 5>;{подключение модулей}
{Раздел описания локальных типов, констант, переменных, процедур и функций (доступны только процедурам и функциям этого модуля). Тексты процедур и функций, объявленных в интерфейсной части модуля}
Const …….
Type …….
Var ……
Initialization
{Раздел операторов, выполняемых при инициализации (подключении). Выполняется до первого оператора программы, использующей модуль. Можно воспользоваться для присвоения переменным модуля начальных значений или создания динамических переменных}
Finalization
{Раздел операторов, выполняемых при завершении работы. Можно воспользоваться для удаления динамических переменных}
end.
После заголовка, содержащего служебное слово unit и идентификатор имени модуля (имя модуля и имя файла с расширением pas, в котором записан модуль, должны обязательно совпадать), идет внешний раздел interface (интерфейсная часть модуля). Все, описанное в этом разделе, доступно из программы и других модулей, использующих этот модуль. В интерфейсной части описываются только заголовки процедур и функций – имя и список формальных параметров. Тело (текст) этих подпрограмм должно находиться в следующей части модуля, после слова implementation. В разделе interface могут быть подключены другие модули с помощью служебного слова uses. Перекрестные ссылки модуля на модуль в интерфейсной части запрещены (модуль А подключает модуль В, а модуль В подключает модуль А). При необходимости, для избежания перекрестных ссылок их можно сделать в исполнительной части.
Раздел реализации (исполнительная часть модуля) implementation предназначен для написания текстов процедур и функций из интерфейсной части модуля, а также для определения локальных (видимых только в этом модуле) констант, типов, переменных и подпрограмм.
После необязательного служебного слова Initialization начинается секция операторов, выполняемых при инициализации.
После необязательного служебного слова Finalization начинается секция операторов, выполняемых при завершении работы.
Пример модуля для вычисления расстояний между точками на плоскости и площади треугольника, заданного тремя точками.
Приведем пример модуля Lib, содержащего описание типа и две функции для вычисления расстояния между двумя точками на плоскости и площади треугольника, и программы, использующей этот модуль.
Листинг модуля Lib.pas
Unit lib;
Interface
Type
Tdot=Record
x , y : Real;// координаты точки x и y
end;
Function Distance(d1,d2:Tdot):real; // расстояние между точками d1 и d2
Function SquareT(d1,d2,d3:Tdot):real; // площадь треугольника, заданного 3-мя точками
Implementation
Function Distance(d1,d2:Tdot):real;
begin
Result := Sqrt(Sqr(d1.x-d2.x)+Sqr(d1.y-d2.y));
end;
Function SquareT(d1,d2,d3:Tdot):real;
var a, b, c, p : Real;
begin
a := Distance(d1,d2); // находим расстояние между точками d1 и d2
b := Distance(d2,d3); // находим расстояние между точками d2 и d3
c := Distance(d3,d1); // находим расстояние между точками d3 и d1
p := (a + b + c)/2)
Result := Sqrt(p * ( p – a ) * ( p – b ) * ( p – c ) );
end;
end.
Листинг программы TesLib, использующей модуль Lib.pas
{Программе доступны: тип Tdot и функции Distance, SquareT. Программа считывает с клавиатуры координаты трех вершин треугольника, вычисляет и выводит на экран площадь треугольника и его периметр.}
program TestLib;
{$APPTYPE CONSOLE}
uses
SysUtils,
Lib; // подключение модулей SysUtils и Lib
var a, b, c : Tdot;
s : real;
begin
write(‘Введите координаты X и Y 1-й вершины треугольника - ’);
readln(a.x, a.y);
write(‘Введите координаты X и Y 2-й вершины треугольника - ’);
readln(b.x, b.y);
write(‘Введите координаты X и Y 3-й вершины треугольника - ’);
readln(c.x, c.y);
s := SquareT(a, b, c);
writeln(‘Площадь треугольника = ’,s:6:2);
p:= Distance(a, b)+ Distance(b, c)+ Distance(c, a);
writeln(‘Периметр треугольника = ’, p:6:2);
readln;
end.
Пример модуля, реализующего стек с целыми числами.
Приведем пример модуля Steck, который содержит минимальный набор процедур и функций для работы со стеком и сами данные. Стек можно организовать на основе массива из целых чисел M. Для контроля над заполнением массива новыми значениями введем целочисленную переменную top, которая всегда будет хранить номер свободной ячейки массива. Причем данные опишем в исполнительной части массива, исключив прямое обращения к ним из программы, использующей модуль. Обращаться к ним будем только с помощью процедур и функций. Таким скрытием данных можно дополнительно гарантировать корректность работы пользователя со стеком (при прямом неправильном изменении переменной top можно потерять некоторые данные из стека, например оператор top:=0 очистит весь стек). Пользователям, подключающим модуль необходимо предоставить методы для работы со стеком: поместить число в стек, извлечь число из стека, проверить стек на пустоту и т.д. Эти процедуры и функции необходимо поместить в интерфейсную часть модуля. Так как, структура хранения данных стека не доступна из программы, то физическая реализация стека может быть совершено различной: динамический массив, связный список. Но программы, которые будут использовать этот модуль не должны изменяться при изменении реализации стека. Они будут пользоваться одним и тем же набором процедур и функций, описанных в интерфейсной части. То есть при изменении способа реализации стека интерфейсная часть модуля остается неизменной, а меняется текст и данные в исполнительной части.
Структура стека на базе массива изображена на рис.1. Новый элемент будет добавляться на место с номером top, после этого top необходимо увеличить на единицу. При извлечении элемента из стека top уменьшается на единицу и из этой позиции извлекается очередное число. Теперь эта позиция считается пустой. Стек пустой – если значение top равно 0. Для инициализации стека (его очистки) достаточно переменной top присвоить 0. В программе извлечение числа из пустого стека приведет к ошибке, поэтому перед такой операцией пользователь должен убедиться, что в стеке есть элементы. Стек организуем на базе динамического массива. Его размер можно увеличивать по мере заполнения стека новыми значениями. Массив окажется полностью заполненным, если число элементов совпадет с top. Это необходимо проверять перед добавлением нового элемента.
Рис.1 Структура стека на базе массива
Листинг модуля Steck.
Unit Steck; {файл Steck.pas}
Interface
Procedure Push(x:integer); //Поместить число х в стек.
Function Pop:integer; // Извлечь число из стека.
Procedure InitSteck; // Очистить стек.
Function IsEmpty:Boolean; // Результат True – если стек пустой.
Implementation
Var M:array of integer;
Top: integer;
Procedure Push(x:integer); //Поместить число х в стек.
begin
if top=High(M) then SetLength(M, Length(M)+20);
{ Если стек заполнен, то увеличиваем число его элементов на 20, High(M) - номер последнего элемента, Length(M) – количество элементов в динамическом массиве, SetLength – задание числа элементов в массиве. }
M[top]:=x;
Inc(top);
end;
Function Pop:integer; // Извлечь число из стека.
begin
top:=top-1; // Dec(top)
Result:=M[top];
end;
Procedure InitSteck; // Очистить стек.
begin
top:=0;
end;
Function IsEmpty:Boolean; // Результат True – если стек пустой.
begin
Result:=top=0;
end;
Initialization
InitSteck; // Проводим инициализацию стека
SetLength(M,20); // Задаем размер стека в 20 элементов
end.
В модуль Steck можно добавить и другие функции, например печати элементов без их извлечения, определения числа элементов в стеке и т.д. Приведем пример программы, использующей стек. В программе последовательно вводятся и помещаются в стек целые числа до первого отрицательного значения. При извлечении их из стека будем выводить их на экран. В результате получим обратную последовательность чисел.
Листинг программы TestSteck.
Program TestSteck;
Uses Steck;
Var n:integer;
begin
repeat
Write(‘Введите число ‘);
Readln(n);
Push(n);
until n<0;
While not IsEmpty do // Пока стек не пустой, извлекаем элемент и печатаем.
begin
n:=Pop;
Write(n,’ ‘);
end;
Readln;
end.
Модули Delphi
Модуль Math
В модуле Math Delphi находиться много полезных математических функций, отсутствующих в стандартной реализации языка Паскаль.
Тригонометрические функции – все угловые параметры и результаты измеряются в радианах:
Function ArcCos(x : Extended): Extended; {параметр |x|<=1, результат [0..Pi] радиан}
Function ArcSin(x : Extended): Extended; {параметр |x|<=1, результат [0..Pi] радиан}
Function Arctan2(y,x : Extended): Extended; {вычисляет арктангенс y/x и возвращает угол [-Pi..Pi] в правильный квадрант}
Procedure SinCos((const Theta: Extended; var Sin, Cos: Extended); {Процедура SinCos работает в 2 раза быстрее, чем вызов функций Sin(), Cos() по отдельности. По углу Theta вычисляет и передает через параметры-переменные значения функций Sin, Cos}
Function Tan(const X: Extended): Extended;
Function Cotan(const X: Extended): Extended; {1/tg(x)}
Функции преобразования углов:
Function DegToGrad(const Degrees: Extended): Extended; {преобразует градусы в радианы radians = degrees*(pi/180).}
Function RadToDeg(const Radians: Extended): Extended; {преобразует радианы в градусы degrees = radians*(180/pi).}
Гиперболические функции:
Function Cosh(const X: Extended): Extended;
Function Sinh(const X: Extended): Extended;
Function Tanh(const X: Extended): Extended;
Function ArcCosh(const X: Extended): Extended;
Function ArcSinh(const X: Extended): Extended;
Function ArcTanh(const X: Extended): Extended;
Логарифмические функции:
Function Log10(const X: Extended): Extended; {логарифм по основанию 10 от Х}
Function Log2(const X: Extended): Extended; {логарифм по основанию 2 от Х}
Function LogN(const Base, X: Extended): Extended; {логарифм по основанию Base от Х}
Суммы величин:
function Sum(const Data: array of Double): Extended; {сумма элементов вещественного массива Data – результат вещественный}
function SumInt(const Data: array of Integer): Integer; {сумма элементов целочисленного массива Data – результат целый}
function SumOfSquares(const Data: array of Double): Extended; {сумма квадратов элементов вещественного массива Data – результат вещественный}
procedure SumsAndSquares(const Data: array of Double; var Sum, SumOfSquares: Extended) {вычисление суммы элементов Sum и суммы квадратов элементов SumOfSquares вещественного массива Data – результатs вещественные}
Минимальная величина массива данных:
function MinValue(const Data: array of Double): Double; {нахождение минимального значения среди элементов вещественного массива Data - результат вещественный}
function MinIntValue(const Data: array of Integer): Integer; {нахождение минимального значения среди элементов целочисленного массива Data - результат целый}
Вычисление минимального значения среди А и В, тип результата определяется типом аргументов:
function Min(A,B: Integer): Integer; overload;
function Min(A,B: Int64): Int64; overload;
function Min(A,B: Single): Single; overload;
function Min(A,B: Double): Double; overload;
function Min(A,B: Extended): Extended; overload;
Максимальная величина массива данных:
function MaxValue(const Data: array of Double): Double; {нахождение максимального значения среди элементов вещественного массива Data - результат вещественный}
function MaxIntValue(const Data: array of Integer): Integer; {нахождение максимального значения среди элементов целочисленного массива Data - результат целый}
Вычисление максимального значения среди А и В, тип результата определяется типом аргументов:
function Max (A,B: Integer): Integer; overload;
function Max (A,B: Int64): Int64; overload;
function Max (A,B: Single): Single; overload;
function Max (A,B: Double): Double; overload;
function Max (A,B: Extended): Extended; overload;
Среднее значение массива данных:
function Mean(const Data: array of Double): Extended; {нахождение среднего значения элементов вещественного массива Data - результат вещественный}
procedure MeanAndStdDev(const Data: array of Double; var Mean, StdDev: Extended); {нахождение среднего значения Mean и среднеквадратичного отклонения StdDev элементов вещественного массива Data - результаты вещественные}
Модуль SysUtils
В стандартном модуле Delphi SysUtils определено огромное количество процедур и функция для работы с файлами, дисками, ошибками, строками и т.д. Приведем краткое описание подпрограмм для обработки и форматирования строк:
function AnsiUpperCase(const S: string): string; - Возвращает строку S в верхнем регистре, с учетом национальных символов (только для кодировки Windows).