Лабораторная
 

Лабораторная работа №2

Модули

Цель работы - овладение практическими навыками и приемами разработки программ с помощью разрабатываемых программистом собственных модулей.

  1. Теоретическая часть

    1. Структура модулей

Структура модуля аналогична структуре программы, однако, есть несколько существенных различий. Она имеет вид:

unit <имя>; {зарезервированное слово (единица); начинает заголовок модуля};

interface {зарезервированное слово (интерфейс), начинает интерфейсную часть модуля}

uses <список модулей>; {необязательный}

{глобальные описания}

implementation {зарезервированное слово (выполнение); начинает исполнительную часть};

uses <список_модулей>; {необязательный}

{локальные описания}

{реализация процедур и функций}

begin {начало инициирующую часть};

{код инициализации}

end. {зарезервированное слово - признак конца модуля}

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

    1. Связь модулей друг с другом

Заголовок модуля состоит из зарезервированного слова UNIT и следующего за ним имени модуля. Для правильной работы среды ТР и возможности подключения средств, облегчающих разработку крупных программ, это имя должно совпадать с именем дискового файла, в который помещается исходный текст модуля. Если например, имеет заголовок

Unit Global;

то исходный текст соответствующего модуля должен размещаться в дисковом файле Global.pas. Имя модуля служит для его связи с другими модулями и основной программой. Эта связь устанавливается специальным предложением. Эта связь устанавливается специальным предложением

Uses <список модулей>

2.1. Демонстрационные примеры

Пример 2.1. Напишем небольшой модуль. Назовем его IntLib и включим в него две простые подпрограммы для целых чисел - процедуру ISwap и функцию IMax:

unit IntLib;

interface

procedure ISwap(var I,J : integer);

function IMax(I,J : integer) : integer;

implementation

procedure ISwap;

var

temp : integer;

begin

temp := I; I := J; J := Temp

end; {конец процедуры ISwap}

function IMax;

begin

if I > J then IMax := I else IMax := J

end; {конец функции IMax}

end. {конец модуля IntLib}

Наберите этот модуль, запишите его в файл INTLIВ.PAS, а за тем скомпилируйте его. В результате получим код модуля в файле INTLIВ.ТРU. Перешлем его в каталог модулей (если такой имеется), или оставив в том же каталоге, где находится следующая программа, которая использует модуль IntLib:

program IntTest;

uses IntLib;

var

A,B : integer;

begin

Write('Введите два целочисленных значения: ');

Readln(A,B);

ISwap(A,B);

Writeln('A = ',A,' B = ',B);

Writeln('Максимальное значение равно ',IMax(A,B));

end. {конец программы IntTest}

Пример 2.2. Написать программу проверяющая является ли квадратная матрица n x n магическим квадратом, т.е. сумма всех элементов всех строк и столбцов равны.

Program Integral;

Uses crt, mymenu;

Var i,j,n,m,t: integer;

ms: mymas;

ch: boolean;

begin

textbackground(blue);

ms[1]:='ввод'; ms[2]:='Проверка'; ms[3]:='Выход';

repeat

clrscr;

menu(ms,3,n);

gotoXY(3,3);

textcolor(1);

case n of

1: begin

textbackground(1);

clrscr;

textcolor(red);

writeln(`Введите размер матрицы m: ');

readln(m);

for i:=1 to m do

for j:=1 to m do

begin

write(i,'- ая строка', j,'-ый столбец');

readln(a[i,j]);

end;

b:=a;

clrscr;

end;

2: begin

textbackground(1);

r2(b,m);

clrscr;

end;

3: halt;

end;

until l = 0;

readln;

end.

Модуль программы MyMenu.tpu:

Unit MyMenu;

interface

uses dos;

type mymas = array[1..3] of string [25];

masiv = array[1..20,1..20] of integer;

procedure menu (af: mymas; nom: integer; var vh: integer);

procedure r2 (a1: masiv; n1: integer);

implementation

uses crt;

var ch :char;

ay :integer;

p,i,x,y :integer;

l,m,r :boolean;

function ResetMouse:boolean;

var r: registers;

begin

r.ax :=0;

intr ($33,r);

ResetMouse := r.ax =$FFFF;

end;

procedure ShowMouseCursor;

var r: registers;

begin

r.ax := 1;

intr ($33,r);

end;

procedure HideMouseCursor;

var r: registers;

begin

r.ax := 2;

intr ($33,r);

end;

procedure ReadMouseState(var x,y: integer; var lb,mb,rb: boolean);

var r: registers;

begin

r.ax:= 3;

intr ($33,r);

x := r.cx;

y := r.dx;

lb := (r.bx and 1) <> 0;

rb := (r.bx and 2) <> 0;

mb := (r.bx and 4) <> 0;

end;

procedure MoveMouseCursor( x,y: integer);

var r: registers;

begin

r.ax:= 4;

r.cx:= x;

r.dx:= y;

intr ($33,r);

end;

procedure as (x,y: byte; an: integer; car,col: byte);

begin

textcolor(col);

gotoXY(x,y);

for p:=1 to an do write(chr(car));

end;

procedure as_tek(x,y:byte; str: string; col,bc_col:byte);

begin

textbackground(bc_col);

textcolor(col);

gotoXY(x,y);

write(str);

textbackground(0);

end;

procedure Menu;

var i,x,y :integer;

l,m,r :boolean;

label st;

begin

ShowMouseCursor;

MoveMouseCursor(0,0);

textbackground(blue);

textcolor(3);

gotoXY(26,6);

write(` -----Menu-------');

for p:=7 to 7+nok-1 do

begin

gotoXY(26,p); write(`|'); gotoXY(40,p); write(`|');

end;

gotoXY(26,6+nom+1);

write(`---------------------');

for y:=1 to nom do

as_tek(28,y+6,af[y],6+blink,1);

as (27,7,13,219,2);

as_tek(28,7,af[1],0,2);

ay:=7;

st:

repeat

if keypressed then ch:=readkey else

begin

ch:='1';

ReadMouseState(x,y,l,m,r);

for i:=7 to 6+nom do

if l and (y div 8+l=i) and (x div 8+l>26) and (x div 8+l<40) then

begin

as(27,ay,13,219,1); as_tek(28,ay,af[ay-6], 6+blink,1);

ay:=i;

as(27,ay,13,219,2); as_tek(28,ay,af[ay-6], 0,2);

textcolor(6);

ch:=#13;

end;

delay(1000);

end;

case ch of

#80,#72,#45:

begin

sound(400); delay(600); nosound;

end;

#13:

begin

sound(400); delay(600); nosound;

end; {case}

case ch of

#80

begin

as(27,ay,13,219,1); as_tek(28,ay,af[ay-6], 6+blink,1);

inc(ay);

if ay=6+nom+1 then ay:=7;

as(27,ay,13,219,2); as_tek(28,ay,af[ay-6], 0,2);

end;

#72:

begin

as(27,ay,13,219,1); as_tek(28,ay,af[ay-6], 6+blink,1);

dec(ay);

if ay=6 then ay:=6+nom;

as(27,ay,13,219,2); as_tek(28,ay,af[ay-6],0,2);

end;

#45,#3:

begin

vh:=45;

halt;

end;

end; {case}

until ch=#13;

vh:=ay-6;

end;

procedure r2(al:massiv; n1:integer);

var i, y :integer;

sum, sumi :integer;

s :byte;

begin

sum:=0; s:=1;

clrscr;

for i:=1 to n1 do

sum:= sum+a1[i,1];

for j:=1 to n1 do

begin

sumi:=0;

for i:=1 to n1 do

sumi:= sum+a1[i,j];

if s=1 then

if sumi<>sum then

s:=0;

end; {for}

for i:=1 to n1 do

begin

sumi:=0;

for j:=1 to n1 do

sumi:= sum+a1[i,j];

if s=1 then

if sumi<>sum then s:=0;

end; {for}

gotoXY(1,1);

textColor(red);

for I:=1 to n1 do

begin

for j:=1 to n1 do

write(al[i,j]:3);

writeln;

end;

if s=1 then

begin

writeln(`Матрица образует магический квадрат');

end

else

begin

writeln(`Матрица не образует магический квадрат');

end;

delay(10000);

repeat

readMouseState(x,y,l,m,r);

until (keypressed or l);

end;

end.

2.2. Практическая часть

Задача 2.1. Разработать модули для решения алгебраических задач:

A. Модуль приближенного решения алгебраических и трансцендентных уравнений;

B. Модуль приближенного вычисления интеграла.

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

Пример 2.3.

unit Proc;

interface

type

MathFunc = function(x: Real): Real;

function Area(a, b: Real; n: Integer; f: MathFunc): Real;

implementation

function Area(a, b: Real; n: Integer; f: MathFunc): Real;

var

i: Integer;

s, h, c, d: Real;

begin

s := 0;

h := (b-a)/n;

for i:= 1 to n do

begin

c := a+h*(i-1);

d := a+h*i;

s := s+h*(f(c)+f(d))/2;

end; { for }

Area := s;

end; { Area }

end. {Proc}

Здесь функция приближенного вычисления определенного интеграла методом трапеций Area имеет четыре параметра: a, b, n и f. A и b имеют тип Real, представляющие соответственно начало и конец интервала, на котором выполняется аппроксимация; n - это целое число подынтервалов; f - формальный параметр процедурного типа MathFunc, используемый в качестве имени функции. Фактический параметр, связанный с f, должен быть именем функции вещественного типа. Эта функция определяет кривую, площадь под которой вычисляется.

Программа, тестирующая функцию Area для подынтегральной функции

f(x) = x2 - x может иметь вид

Пример 2.4.

program ProcTypeDemo;

uses Crt, Proc;

var

a, b: Real;

n: Integer;

{$F+}

function Func(x: Real): Real;

begin

Func := Sqr(x)-x;

end;

{$F-}

begin

ClrScr;

Write('введите нижнюю граница интервала A:= '); Readln(a);

Write('введите верхнюю граница интервала B:= '); Readln(b);

Write('введите число подинтервалов N:= '); Readln(n);

Writeln('---------------------------------------------');

Writeln(' площадь под кривой S:-= ', Area(a,b,n,Func):10:2);

Readln;

end. {ProcTypeDemo}

Задача 2.2.

В программе, тестирующей функции модуля, сравнить методы приближенного решения алгебраических и трансцендентных уравнений (методы приближенного вычисления интеграла), поочередно используя их для решения одного и того же уравнения (для одной и той же подынтегральной функции). Значение e (точность) следует поочередно брать равными 0.01, 0.001, ..., 0.0000001. Для каждого из методов построить график или столбчатую диаграмму изменения числа потребовавшихся приближений при переходе от одного значения к другому.

3. Задачи, для самостоятельного решения

Приближенно вычислить интеграл:

b

Z= F(x) dx

а

на заданном отрезке [а;b] в соответствии с вариантом задания. Считать заданным число разбиений отрезка интегрирования n и численный метод решения. Включить в программу вычисление точного значения интеграла.

На печать вывести приближенное, точное значения интеграла и относительную погрешность вычисления в процентах.

Вар.

зад.

Подынтеграл. функция

f (x)

Первообразные F(х)=∫ f (x) dx

Метод числен. решения

Число отрезков

Интервал интегр.

Требуем. точность

1.

Ln²(x) / x

Ln³(x)/3

Трап.

60

[1;4]

10-4

2.

(1/x²)sin(1/x)

Cos(1/x)

Прям.

50

[1;2,5]

0,5 10-3

3.

Xx (1 + lnx)

X x

Трап.

40

[1;3]

10-4

4.

Cos(x)

Sin(x)

Трап.

60

[0; π/2]

10-4

5.

Sin²(x)

X/2-(sin2x) /4

Трап.

60

[0; π/2]

0,5 10-3

6.

X ex sin x

[x sinx+ (1-x) cosx] (e x / 2)

Трап.

100

[0; 1]

10-4

7.

(ln x/x

-[ln x +2lnx+2] (1/x)

Прям.

50

[0; 2,5]

10-4

8.

X arctgx

(arctg(x²-1)-x) / 2

Трап.

50

[0;3]

0,5 10-3

9.