Модульное программирование 1 Павловская Т.А. (СПбГУИТМО) Подпрограммы 2 Павловская Т.А. (СПбГУИТМО) Общие положения Логические законченные части программы оформляются в виде подпрограмм Подпрограмма — это фрагмент кода, к которому можно обратиться по имени Подпрограмма записывается один раз, а вызываться может столько раз, сколько необходимо Одна и та же подпрограмма может обрабатывать различные данные, переданные ей в качестве параметров. Павловская Т.А. (СПбГУИТМО) 3 Структура программы Главная Глобальные переменные Подпрограмма А Локальные переменные begin ... end Подпрограмма В Подпрограмма С begin Вызов А ... Вызов А ... Вызов В ... ... end Павловская Т.А. (СПбГУИТМО) 4 Структура программы в оперативной памяти В IBM PC-совместимых компьютерах память условно разделена на сегменты. Динамическая память Сегмент стека Сегмент данных Адрес каждого байта составляется из номера сегмента и смещения. Компилятор формирует сегмент кода, в котором хранится программа в виде машинных команд, и сегмент данных, в котором выделена память под глобальные переменные программы. Сегмент кода 16 бит 4 бита Адрес сегмента + 0000 16 бит Смещение Физический адрес 20 бит Павловская Т.А. (СПбГУИТМО) 5 Виды переменных Глобальными называются переменные, которые описаны в главной программе. Время жизни глобальных переменных — с начала программы и до ее завершения. Располагаются в сегменте данных. В подпрограммах описываются локальные переменные. Они располагаются в сегменте стека, причем распределение памяти происходит в момент вызова подпрограммы, а ее освобождение — по завершении подпрограммы. Локальные переменные автоматически не обнуляются. Павловская Т.А. (СПбГУИТМО) 6 Вызов Для того чтобы подпрограмма выполнилась, ее надо вызвать. Вызов подпрограммы записывается в том месте программы, где требуется получить результаты работы. Процедура вызывается с помощью отдельного оператора, а функция — в правой части оператора присваивания, например: inc(i); writeln(a, b, c); { вызовы процедур } y := sin(x) + 1; { вызов функции } Павловская Т.А. (СПбГУИТМО) 7 Процедуры заголовок procedure <имя> [(список параметров)]; <разделы описаний> begin <раздел операторов> end; Павловская Т.А. (СПбГУИТМО) 8 Пример процедуры Вычислить разность между средними арифметическими значениями элементов двух вещественных массивов program dif_average; const n = 3; type mas = array[1 .. n] of real; var a, b : mas; i : integer; dif, av_a, av_b : real; Павловская Т.А. (СПбГУИТМО) 9 procedure average(x : mas; var av : real) var i : integer; begin av := 0; for i := 1 to n do av := av + x[i]; av := av / n; Главная программа end; begin for i := 1 to n do read(a[i]); for i := 1 to n do read(b[i]); average(a, av_a); average(b, av_b); dif := av_a - av_b; writeln('Разность значений ', dif:6:2) end. Павловская Т.А. (СПбГУИТМО) 10 Функции заголовок function <имя> [(список параметров)] : <тип>; <разделы описаний> begin <раздел операторов> <имя> := <выражение>; end; Павловская Т.А. (СПбГУИТМО) 11 Пример функции program dif_average1; const n = 3; type mas = array[1 .. n] of real; var a, b : mas; i : integer; dif : real; Павловская Т.А. (СПбГУИТМО) 12 function average(const x : mas): real; var i : integer; av : real; begin av := 0; for i := 1 to n do av := av + x[i]; average := av / n; Главная программа end; begin for i := 1 to n do read(a[i]); for i := 1 to n do read(b[i]); dif := average(a) - average(b); writeln('Разность значений ', dif:6:2) end. Павловская Т.А. (СПбГУИТМО) 13 Виды параметров подпрограмм 14 Павловская Т.А. (СПбГУИТМО) Обмен данными Через глобальные переменные Через параметры Параметры передаются: По значению По адресу (var или const) Павловская Т.А. (СПбГУИТМО) Типы параметров: Значения Переменные Константы Бестиповые Открытые Процедурные Объекты 15 Параметры и аргументы При вызове подпрограммы после ее имени в скобках указываются аргументы, то есть те конкретные величины, которые передаются в подпрограмму Список аргументов как бы накладывается на список параметров и замещает их, поэтому аргументы должны соответствовать параметрам по количеству, типу и порядку следования. Для каждого параметра обычно задается его имя, тип и способ передачи. Либо тип, либо способ передачи могут не указываться. В заголовке подпрограммы нельзя вводить описание нового типа. Павловская Т.А. (СПбГУИТМО) 16 Параметр-значение имя : тип; Например: procedure P(x : integer); При вызове подпрограммы на месте параметра, передаваемого по значению, может находиться выражение: P(x); P(3); P(1.2); P(a + b/2); Тип выражения должен быть совместим по присваиванию с типом параметра. Павловская Т.А. (СПбГУИТМО) 17 Параметр-переменная var имя : тип; Например: procedure P(var x : integer); При вызове подпрограммы на месте параметра-переменной может находиться только ссылка на переменную точно того же типа: P(a); P(x); Павловская Т.А. (СПбГУИТМО) 18 Параметр-константа const имя : тип; Например: procedure P(const x : integer); При вызове подпрограммы на месте параметра может быть записано выражение, тип которого совместим по присваиванию с типом параметра. Павловская Т.А. (СПбГУИТМО) 19 Пример var a, b, c, d, e : real; procedure XaXa(a, b: real; c : real; var d : real); var e: real; begin c := a + b; d := c; e := c; writeln (‘c=‘, c, ‘ d=‘, d, ‘ e=‘, e); end; begin а :=3; b :=5; XaXa(a, b, c, d); writeln (‘c=‘, c, ‘ d=‘, d, ‘ e=‘, e); end. Павловская Т.А. (СПбГУИТМО) с= 8 d= 8 e= 8 с= 0 d= 8 e= 0 20 Пример Заголовок процедуры имеет вид: Procedure P(a:real; b:char; var c:real); Переменные в вызывающей программе описаны так: Var a:integer; b,c:char; d,x:real; -------------------------- P(a, b, c); P(d+a, c, x); P(x, ’c’, d); P(a, b, a+1); Павловская Т.А. (СПбГУИТМО) 21 Итоги Для передачи в подпрограмму исходных данных испольуются параметры-значения и параметры-константы. Параметры составных типов (массивы, записи, строки) предпочтительнее передавать как константы. Результаты работы процедуры следует передавать через параметры-переменные, результат функции — через ее имя. Павловская Т.А. (СПбГУИТМО) 22 Открытый массив Может быть только одномерным и состоять из элементов любого типа, кроме файлового. На место открытого массива можно передавать одномерный массив любой размерности, состоящий из элементов такого же типа Элементы массива нумеруются с нуля. Номер максимального элемента в массиве можно определить с помощью функции High. Пример. Функция, определяющая максимальный элемент любого целочисленного массива. function max_el(const mas : array of integer) : integer; var i, max : integer; begin max := mas[0]; for i := 0 to High(mas) do if mas[i] > max then max := mas[i]; max_el := max; end; Павловская Т.А. (СПбГУИТМО) 23 Открытые строки По значению и на место параметра-константы можно передавать строки произвольной длины. Для передачи в подпрограмму по адресу строк любой длины используется: либо специальный тип OpenString, называемый открытой строкой либо тип string при включенном режиме {$P+} type s20 = string[20]; var s1 : string[40]; s2 : string[10]; procedure P(const x : s20; y : string; var z : openstring); ... begin ... end. Павловская Т.А. (СПбГУИТМО) P(s2, s1, s1); ... 24 Бестиповые параметры Function EQ(var x, y; size: word): boolean; Type Bytes = array[0 .. MaxInt] of byte; Var xb: Bytes absolute x; yb: Bytes absolute y; n : integer; Begin N :=0; While (n < size) and (xb[n] = yb[n]) do inc(n); EQ := n = size; End; Павловская Т.А. (СПбГУИТМО) 25 С помощью функции EQ можно сравнить две любые величины. Пусть, например, в программе описаны переменные: var a, b : array [1 .. 10] of byte; x: real; c: string; Следующие обращения к функции EQ будут корректны: EQ(a, b, sizeof(a)) { сравнение двух массивов } EQ(a[2], b[5], 4) { сравнение 2–5 элементов массива "a" с 5–8 элементами массива "b", соответственно } EQ(c, x, sizeof(real)) { сравнение первых 6 байт строки с с переменной x } Павловская Т.А. (СПбГУИТМО) 26 Параметры процедурного типа procedure tabl_fun(x, Xk, dX : real; f : fun); begin writeln(' --------------------------- '); writeln('| X | Y |'); writeln(' --------------------------- '); while x <= Xk do begin writeln('|', x:9:2,' |', f(x):9:2,' x := x + dX; end; |'); writeln(' --------------------------- '); end. Павловская Т.А. (СПбГУИТМО) 27 Работа с параметром 1. Определить процедурный тип, например: type fun = function(x : real) : real; 2. Задать для подпрограмм, предназначенных для передачи в качестве параметра, ключ компилятора {$F+}, определяющий дальнюю адресацию, например: {$F+} function Q(x : real) : real; begin Q := 2 * x / sqrt(1 – sin(2 * x)); end; {$F–} Павловская Т.А. (СПбГУИТМО) 28 Рекурсивные подпрограммы Function FTR(n : byte): longint; Begin If (n = 0) or (n = 1) then FTR := 1 Else FTR := FTR(n - 1) * n; End; ---------A := FTR(4); Павловская Т.А. (СПбГУИТМО) 29 Модули 30 Павловская Т.А. (СПбГУИТМО) Структура модуля unit имя; { заголовок модуля } interface { интерфейсная секция модуля } { описание глобальных элементов модуля (видимых извне) } implementation { секция реализации модуля } { описание локальных (внутренних) элементов модуля } begin end. { секция инициализации } { может отсутствовать } Павловская Т.А. (СПбГУИТМО) 31 Состав и использование модуля В интерфейсной секции модуля определяют константы, типы данных, переменные, а также заголовки процедур и функций. В секции реализации описываются подпрограммы, заголовки которых приведены в интерфейсной части. Кроме того, в этой секции можно определять константы, типы данных, переменные и внутренние подпрограммы. Секция инициализации предназначена для присваивания начальных значений переменным, которые используются в модуле. Использование в программе величин, описанных в интерфейсной части модуля: uses Average, Graph, Crt; Павловская Т.А. (СПбГУИТМО) 32 Пример модуля unit Average; interface const n = 10; type mas = array[1 .. n] of real; procedure aver_mas(x : mas; var av : real); implementation procedure aver_mas(x : mas; var av : real); var i : integer; begin av := 0; for i := 1 to n do av := av + x[i]; av := av / n; end; end. Павловская Т.А. (СПбГУИТМО) Использование модуля в программе: program dif_average; uses Average; var a, b : mas; i : integer; dif, av_a, av_b : real; begin for i := 1 to n do read(a[i]); for i := 1 to n do read(b[i]); aver_mas(a, av_a); aver_mas(b, av_b); dif := av_a – av_b; writeln('Разность:', dif:6:2); end. 33 Стандартные модули Паскаля 34 Павловская Т.А. (СПбГУИТМО) Стандартные модули Паскаля System Crt Dos и WinDos Graph Strings Павловская Т.А. (СПбГУИТМО) 35 Модуль System содержит базовые средства языка, которые поддерживают ввод-вывод, работу со строками, операции с плавающей точкой и динамическое распределение памяти содержит все стандартные и встроенные процедуры, функции, константы и переменные Паскаля автоматически используется программах, его не требуется операторе uses Павловская Т.А. (СПбГУИТМО) во всех указывать в 36 Примеры переменных System var HeapOrg: Pointer Указывает на конец динамической памяти. var HeapPtr: Pointer Указывает на начало динамической памяти. var InOutRes: Integer Содержит код последней операции ввода-вывода. Его можно получить с помощью вызова функции IOResult. var Input: Text Назначает стандартный файл ввода. var RandSeed: Longint Содержит начальное значение встроенного генератора случайных чисел. Павловская Т.А. (СПбГУИТМО) 37 Примеры подпрограмм System var RandSeed: Longint function Abs(x) procedure Assign(var f; Name) procedure Continue function Cоpy(s: String; Indx: Integer; Count: Integer): String procedure Dec(var x: <порядковый тип> [; n: Longint]) function Eof[ (var f) ]: Boolean procedure Exit function Exp(x: Real): Real procedure Моvе(var Src, Dst; Count: Word) procedure MkDir(s: String) procedure Randomize Writeln([var f: Text;] v1, [,v2, ..., vn] ) Павловская Т.А. (СПбГУИТМО) 38 Модуль Crt позволяет: выполнять вывод в заданное место экрана заданным цветом символа и фона; открывать на экране окна прямоугольной формы и выполнять вывод в пределах этих окон; очищать экран, окно, строку и ее часть; обрабатывать ввод с клавиатуры; управлять встроенным динамиком. Павловская Т.А. (СПбГУИТМО) 39 Текстовый режим монитора Экран 1 Знакоместо 80 1 Цвет символа Цвет фона 25 Видеопамять Код символа 0 0 1 1 0 0 Атрибут 1 0 0 R G B 0 1 0 Цвет фона 1 R G B 1 1 0 Цвет символа Бит мерцания Павловская Т.А. (СПбГУИТМО) 40 Константы цветов текста Константа Значение Black 0 (черный) Blue 1 (синий) Green 2 (зеленый) Cyan 3 (голубой) Red 4 (красный) Magenta 5 (малиновый) Brown 6 (коричневый) LightGray 7 (светло-серый) DarkGray 8 (темно-серый) LightBlue 9 (светло-синий) LightGreen 10 (светло-зеленый) LightCyan 11 (светло-голубой) LightRed 12 (розовый) LightMagenta 13 (светло-малиновый) Yellow 14 (желтый) White 15 (белый) Blink 128 (мерцание) Павловская Т.А. (СПбГУИТМО) 41 Подпрограммы модуля Crt procedure ClrScr; procedure Delay(Msec: word) procedure GoToXY(X, Y: Byte) function KeyPressed: Boolean procedure NoSound function ReadKey: Char function Sound(Herz: Word) procedure TextBackGroud(Color: byte) procedure TextColor(Color: Byte) function WhereX: Byte function WhereY: Byte procedure Window(X1, Y1, X2, Y2: Byte) … Павловская Т.А. (СПбГУИТМО) 42 Пример Программа создает меню из трех пунктов, управляемое клавишами курсора, а также клавишами Tab и Shift+Tab. Выбор пункта меню выполняется с помощью клавиши Enter. Выход из программы – клавиша Esc. Павловская Т.А. (СПбГУИТМО) 43 program StupidMenu; uses Crt; const n_items = 3; l_item = 10; item: array[1 .. n_items] of string[l_item] = ('item1', 'item2', 'item3'); pos : array[1 .. n_items] of integer = (1, l_item+1, 2*l_item+1); var DefaultMode, ActiveColor, InactiveColor: word; c : char; i, j : word; procedure InitMenu(ActiveColor, InactiveColor: word); var i : word; begin window(1, 1, 80, 2); TextBackGround(LightGray); clrscr; TextColor(InactiveColor); DrawItem(1, ActiveColor); for i := 2 to n_items do DrawItem(i, InactiveColor); gotoXY(1, 2); write(‘_________________________________’); gotoXY(3, 1); end; Павловская Т.А. (СПбГУИТМО) 44 procedure DrawItem(i, Color: word); begin window(1,1,80,2); TextBackGround(LightGray); TextColor(Color); gotoXY(pos[i], 1); write(item[i]); end; procedure DoItem(i: word); { выполнение пункта меню } begin window(3, 4, 78, 24); TextBackGround(LightGray); clrscr; write('Working: item ', i); end; Павловская Т.А. (СПбГУИТМО) 45 begin { главная программа} clrscr; DefaultMode := LastMode; ActiveColor := LightGreen; InactiveColor:= Green; InitMenu(ActiveColor, InactiveColor); i := 1; j := 1; Павловская Т.А. (СПбГУИТМО) 46 while true do begin c := readkey; case ord(c) of 27: break; 13: DoItem(i); 15 {Shift+Tab}, 75 {Left}: begin j := i; dec(i); if i = 0 then i := n_items; end; 9 {Tab}, 77 {Right}: begin j := i; inc(i); if i = n_items + 1 then i := 1; end; end; DrawItem(j, InactiveColor); DrawItem(i, ActiveColor); end; TextMode(DefaultMode); end. Павловская Т.А. (СПбГУИТМО) 47 Модули Dos и WinDos содержат подпрограммы, реализующие возможности операционной системы MS-DOS — например, переименование, поиск и удаление файлов, получение и установку системного времени, выполнение программных прерываний. Для поддержки этих подпрограмм в модулях определены константы и типы данных. Модуль Dos использует строки Паскаля, а WinDos — строки с завершающим нулем. Павловская Т.А. (СПбГУИТМО) 48 Подпрограммы модуля Dos function DiskFree(Disk: byte): Longint; function DiskSizе(Disk: Byte): Longint; procedure Exec(Path, CmdLine: String); procedure FindFirst(Path: String; Attr: Bytе; var S: SearchRec) procedure GetDate(var Year, M, Day, D: Word) procedure GetAttr(var f; var Attr: Word) procedure Intr(IntNum: Byte; var Regs: Registers) procedure SetFAttr(var f; Attr: Word) procedure SetDate(var Y, M, D, Dw: Word) procedure SetTime(var Hour, Min, Sec, Ssec: Word) … Павловская Т.А. (СПбГУИТМО) 49 Пример Программа определяет, сколько русских букв находится во всех текстовых файлах текущего каталога. program count_rus_letters; uses Dos; var Info : SearchRec; code : integer; n : longint; c : char; f : text; begin n := 0; FindFirst('*.txt', AnyFile, Info); while DosError = 0 do begin assign(f, Info.Name); reset(f); while not EOF(f) do begin read(f, c); code := ord(c); if (code > $7F) and (code < $B0) or (code > $DF) and (code < $F2) then inc(n); end; close(f); FindNext(Info); end; writeln('Русских букв в текущем каталоге – ', n) end. Павловская Т.А. (СПбГУИТМО) 50 Модуль Graph обеспечивает: вывод линий и геометрических фигур заданным цветом и стилем; закрашивание областей заданным цветом и шаблоном; вывод текста различным шрифтом, заданного размера и направления; определение окон и отсечение по их границе; использование графических спрайтов и работу с графическими страницами. Павловская Т.А. (СПбГУИТМО) 51 Использование графики 1. подключение модуля Graph; 2. перевод экрана в графический режим; 3. установка параметров изображения; 4. вывод изображения; 5. возврат в текстовый режим. Павловская Т.А. (СПбГУИТМО) 52 Примеры типов модуля Graph type LineSettingsType = record LineStyle : Word Pattern : Word Thickness : Word end type TextSettingsType = record Font, Direction, CharSize: Word Horiz, Vert: Word end type ArcCoordsType X, Y XStart, Ystart XEnd, Yend end Павловская Т.А. (СПбГУИТМО) = record : Integer : Integer : Integer 53 Примеры констант модуля Graph Константы образцов закрашивания Константы шрифтов Описание Константа Знач ение EmptyFill 0 0 (растровый шрифт 88) Закрашивание области фоновым цветом SolidFill 1 1 (векторный шрифт) Непрерывное закрашивание области LineFill 2 Закрашивание --------------------- SmallFont 2 ltSlashFill 3 Закрашивание ///// SanSerifFont 3 SlashFill 4 GothicFont 4 Закрашивание жирными линиями //// HorizDir 0 (слева направо) VertDir 1 (сверху вниз) Значение Константа DefaultFont TriplexFont Константы стиля линии Значение Константа Павловская Т.А. (СПбГУИТМО) SolidLn 0 (непрерывная) DottedLn 1 (линия из точек) NormWidth 1 (обычная толщина) ThickWidth 3 (жирная линия) 54 Примеры подпрограмм модуля Graph procedure Arс(Х, Y: Integer; Angle1, Angle2, R: Word) procedure Circlе(Х, Y: Integer; R: Word) procedure CloseGraph procedure FillPoly(N : Word; var S) function GetColor: Word function GetMaxX: Integer function GraphResult: Integer procedure InitGraph(var GrDriver: Integer; var Mode: Integer; Path : String) procedure Line(X1, Y1, X2, Y2: Integer) procedure OutTextXY(Х, Y: Integer; S: String) procedure PutImage(X, Y: Integer; var Mass; Oper: Word) procedure Rectangle(X1, Y1, X2, X2: Integer) procedure SetBkColor(Color: Word) procedure SetColor(Color: Word) procedure SetLineStyle(SType: Word; Pattern: Word; S: Word) procedure SetVisualPage(Page: Word) Павловская Т.А. (СПбГУИТМО) 55 Пример pole The end uses Graph; const grDriver : integer = Detect; pole = 20; var grMode : integer; maxX, maxY : integer; begin { -----------------------------инициализация графики ----- } InitGraph(grDriver, grMode, 'd:\tp\bgi'); if GraphResult <> GrOK then begin writeln('Ошибка графики: ', GraphErrorMsg(ErrCode)); exit end; { ------------------------------------------ вывод линий ----- } maxX := GetMaxX; maxY := GetMaxY; Line(pole, maxY div 2, maxX - pole, maxY div 2); Line(maxX div 2, pole, maxX div 2, maxY - pole); { ------------------------------------------ вывод текста ----- } SetColor(Cyan); SetTextStyle(GothicFont, HorizDir, 4); OuttextXY(pole, pole, 'The end'); readln; CloseGraph end. Павловская Т.А. (СПбГУИТМО) 56