Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Egorova1

.pdf
Скачиваний:
36
Добавлен:
14.02.2015
Размер:
1.67 Mб
Скачать

Основная программа - это модуль, который вызывается только операционной системой. Каждому модулю присваивается имя, и модульная структура программы изображается в виде диаграммы (иерархическая схема модулей).

Пример 1. Ниже приведен пример иерархической схемы модулей.

 

 

 

 

 

 

 

 

 

 

А - основная программа.

 

 

 

 

 

 

A

 

 

 

 

 

 

 

 

 

 

 

 

 

D,F,B,C - подпрограммы.

 

 

 

 

 

 

 

 

 

 

D,F - только вызываемые модули.

 

 

B

 

 

C

 

 

 

 

B,C - одновременно и вызываемые,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

и вызывающие модули.

 

D

 

 

 

F

 

 

Модуль может быть помещен (записан) в системную библиотеку, в пакет прикладных

программ, в библиотеку пользователя, в программу пользователя.

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

Пример 2. Модули для вычисления значения функций sinx, cosx и т.д., модули для ввода или вывода значений данных находятся в библиотеке компилятора.

Пример 3. Модули, организующие процесс выполнения заданий на ЭВМ, находятся в библиотеке ОС.

В. Для решения некоторого класса задач пользователь или группа разработчиков создает пакет прикладных программ (ППП), или библиотеку прикладных программ. Модули в ППП имеют конкретное прикладное назначение. Например, существует ППП

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

С. Пользователь может создать свою личную библиотеку и записать в нее свои модули. D. Модуль может быть записан непосредственно в программе. В этом случае

использовать модуль можно только в пределах этой программы.

7.1.2Свойства модулей

a)Завершенность, то есть модуль должен реализовывать логически завершенную часть алгоритма.

b)Независимость, то есть к модулю можно обратиться из любого другого модуля программы или вообще из другой программы.

c)Предсказуемость, то есть алгоритм модуля должен быть реализован так, чтобы в нем не оставалось никаких "воспоминаний" о предыдущих вызовах.

d)Размер модуля должен быть небольшим, чтобы его можно было легко читать и отлаживать (обычно не более 100 операций).

e)Объем данных, на которые модуль может ссылаться, должен быть сведен к минимуму и передаваться, по возможности, через список параметров.

7.2 КЛАССИФИКАЦИЯ МОДУЛЕЙ В ПАСКАЛЕ

 

 

МОДУЛЬ

 

 

Основная программа

 

Подпрограмма (subroutine)

 

 

 

 

 

Типа procedure

 

Типа function

 

 

функция

процедура

 

 

 

131

Модуль обычно оформляют как функцию, если результатом выполнения является одно скалярное значение. Если модуль выдает более одного результата, то его оформляют в виде процедуры.

Пример 1. Вычислить p =

n!

для любых n,m 0

m!(n m)!

 

вход

1

Ввод n,m

2

 

n

0

 

 

и

m

0

 

и

n

m

4

 

 

 

3

Вычислить n!

 

 

 

 

 

 

 

 

Вывод:

 

 

 

 

 

«n,m задано

5

 

 

 

 

 

 

 

 

неверно»

Вычислить m!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6

 

 

 

 

 

Вычислить (n-m)!

 

 

 

 

 

 

 

 

 

 

 

7

 

 

 

 

 

Вычислить p

 

 

 

 

 

 

 

 

 

 

 

8

 

 

 

 

 

Вывод p

 

 

 

 

Вблоках 4,5,6 выполняются одинаковые действия для вычисления факториала, поэтому рекомендуется оформить модуль вычисления факториала FACT. Этот модуль будет в качестве результата выдавать одно число - значение факториала, поэтому рекомендуется этот модуль оформить как функцию.

Впрограмме блокам 4,5,6 будут соответствовать три обращения к модулю FACT с указанием каждый раз конкретного аргумента (n,m и (n-m)).

выхо

Пример 2. Разрабатывается библиотека прикладных программ для работы с комплексными числами. Написать модуль для сложения любых двух заданных чисел.

Дано:

r

вещ. часть

 

 

r

вещ. часть

го числа.

1

 

1го числа;

2

2

 

i1 мнимая часть

 

i2

мнимая часть

 

Результат:

r

вещ. часть

 

суммы 1го и 2

го числа.

 

3

 

 

 

 

i3 мнимая часть

 

 

 

 

Результатов - два, поэтому данный модуль следует оформить как процедуру. Назовем ее

CADD.

Пример 3. Дано две последовательности с одинаковым количеством элементов n 100. В 1-ой последовательности найти минимальный элемент, затем сформировать 3-ю последовательность и в ней найти минимальный элемент. Правило формирования 3-ей последовательности: если сумма двух очередных элементов 1-ой и 2-ой последовательности положительна, то элемент новой последовательности равен этой сумме, деленной на минимальный элемент 1-ой последовательности.

Дано: n - количество элементов в 1-ой, 2-ой последовательности, 1 n 100 , integer;

x1 , x2 ,Kxn 1- ая последовательности: массивы типа real. y1 , y2 ,Kyn 2 - ая

Результаты: Mx = min{x1 , x2 ,Kxn }, real;

z1 , z2 ,Kzk 3 - ая последовательность, real, zi = xiMx+ yi ;

k-количество элементов в новой последовательности; mz = min{z1 , z2 ,Kzk }, real;

D - номер варианта решения.

132

вход

1

Ввод n

 

2

 

1 n 100

F

T

3

4

x 1 , K x n

D=2

 

 

5

y1 , K y n

6

Вычисление MX

T

7

 

 

F

MX 0

 

 

8

 

 

 

11

Получение k,

 

 

 

D=1

z1 , z2 ,Kzk

9

Вычисление MZ

10

D=0

12

Обработка результатов

выход

В блоках 4,5 выполняются одинаковые действия, поэтому следует оформить модуль для ввода с терминала элементов одномерного массива VVOM. Вид модуля - процедура.

В блоках 6,9 выполняются также одинаковые действия, поэтому следует оформить модуль для поиска минимального элемента в заданном одномерном массиве: MINOM. Вид модуля - функция.

В программе блокам 4 и 5 будет соответствовать вызов ПП VVOM, блокам 6 и 9 - вызов ПП MINOM.

7.3 ОБРАЩЕНИЕ К ПОДПРОГРАММЕ

Форма обращения (вызова) зависит от вида подпрограммы (ПП). Вызов функции - это операнд вида:

1)<имя функции>

2)<имя функции> (<список фактических параметров>)

Впервом случае имеем функцию без параметров.

Пример 1. Обращения к стандартным функциям - это, например, операнды вида: sin(0.5), sin(a+b), cos(x), clock.

В программе операторы, в которых производятся эти обращения, могут быть такими: y:=sin(a+b);

if cos(x)>0 then ...

a:=clock; { Функция clock дает время в миллисекундах }

Пример 2. Обращение к функции fact, рассмотренной в примере 1 в п.7.2 - это, например, операнды fact(n), fact(m). Оператор, в котором производятся обращения к функции fact:

p:=fact(n)/(fact(m)*fact(n-m));

133

Вызов процедуры - это оператор процедуры, который относится к простым операторам языка Паскаль. Вид оператора - процедуры:

1)<имя процедуры>

2)<имя процедуры>(<список фактических параметров>.

Впервом случае имеем процедуру без параметров.

Пример 3. Обращения к системным процедурам ввода-вывода: read (a, x, c[i]); writeln;

Фактические параметры (или аргументы) - это значения и идентификаторы, с которыми должна выполниться вызываемая ПП.

Пример 4. Рассмотрим следующие обращения к функциям: sin(0,5), sin(a), sin(a+b). Здесь 0,5; a, (a+b) - фактические параметры.

Отличие вызова функции и процедуры: в то время как вызов процедуры осуществляется с помощью специального оператора, функция вызывается тогда, когда ее имя появляется в выражении. Функцию можно вызвать там, где разрешено использование выражения, тип которого совпадает с типом возвращаемого функцией значения.

В структурной схеме вызов процедуры,

...

например,

form(t,k),

оформляется

 

следующим образом .

 

form (t,k)

 

 

...

7.4 ОБЪЯВЛЕНИЕ ПОДПРОГРАММЫ

Объявление процедуры и (или) функции записывается после раздела объявления переменных var перед begin программы.

Структура объявления подпрограммы (ПП): <заглавие> <разделы описаний>

begin

s1 ; s2 ;Ksn end;

Различия в объявлении, то есть в оформлении, основной программы (PROGRAM) и подпрограммы:

1)форма заглавия;

2)в конце объявления ПП после end ставится ";" (в конце программы - ".").

Остальное: разделы описаний, раздел операторов s1 ; s2 ;Ksn , - записываются по тем же правилам, что и в основной программе.

7.4.1 Заглавие подпрограммы

Заглавие процедуры:

1)procedure <имя процедуры>;

2)procedure <имя процедуры> (<список формальных параметров>); Заглавие функции:

1)function <имя функции>: <тип результата>;

2)function <имя функции> (<список формальных параметров>):<тип результата>;

Вописании заглавий: (1) - это ПП без параметров, (2) - это ПП с параметрами. Основное отличие в заглавии процедуры и функции: для функции надо всегда задавать

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

134

Формальный параметр «a» имеет тип «ОМ». ОМ - это имя типа: одномерный массив из 100 элементов вещественного

Пример 1. Данные заглавия функций неверны, так как тип результата задается не идентификатором типа:

function

A (b:months) : (cocnter, spring, summer, fall);

function

B (b:months) : 1..31.

Список формальных параметров необязателен. Если же он есть, то в нем должны быть перечислены имена формальных параметров и их типы, например:

procedure рr1 (a:real; b:integer; c:char);

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

procedure pr1 (d, e:integer; c:char);

Тип параметра может быть любым, включая и структурированный. Но, как и для результата, для определения типа параметра следует использовать идентификатор типа. (Помните, что описание типа с помощью type используется именно для образования идентификатора вновь создаваемого типа).

7.4.2 Формальные параметры

Формальные параметры - это наименования переменных, через которые передается информация из программы в ПП и наоборот. Обычно в список параметров включают имена переменных, которые являются для ПП исходными данными и результатами, причем именно тех переменных, которым при разных обращениях к ПП соответствуют различные аргументы. Формальные параметры могут быть двух основных видов: параметры-значения и параметры-переменные. Через параметры-значения в подпрограмму обычно передаются исходные данные, а через параметры-переменные передаются результаты выполнения процедуры. Описание в списке формальных параметров параметра-значения:

<имя параметра>:<тип параметра> параметра-переменной:

var <имя параметра>:<тип параметра>

В списке формальных параметров для функции обычно записываются только параметры-значения (то есть результат функции - один, и он передается через имя функции). В списке формальных параметров процедуры могут быть и параметры значения, и параметры-переменные.

Пример 1. Заглавие функции для определения факториала (см. пример 1 из п.7.2):

function

fact

(n : integer)

: integer ;

 

{

14243

123

 

имяфункции

имяформального

типрезультата

параметраиеготти

Пример 2. Заглавие процедуры для сложения двух комплексных чисел (см. пример 2 из

п.7.2):

cadd

( r ,i1 , r2 ,i2 : real ;

var r3 ,i3 : real );

procedure

 

123

1442443

1442443

 

имяпроцедуры

формальныепараметры-

формальныепараметры-

 

 

значенияиих тип

переменныеиих тип

Пример 3. Рассмотрим пример 3 из п.7.2. В примере используются два модуля: модуль для ввода элементов одномерного массива VVOM и модуль поиска минимального элемента одномерной последовательности MINOM. Пусть модуль VVOM используется только в данной программе. Исходные данные для VVOM: a - имя вводимого массива, n- количество элементов. Но при обоих обращениях к VVOM, которые предполагаются для данной программы, количество вводимых элементов будет одинаково, поэтому n можно и не включать в список параметров. Исходные данные для ПП MINOM: a - имя массива, l- количество элементов. Запишем заглавие, разделы объявлений основной программы и объявления модулей VVOM и MINOM .

program TM(i,o);

type OM=array [1..100] of real];

var k,n: integer;

 

 

x,y,z: OM;

 

 

Mx,Mz: real;

 

 

D:integer;

}

 

procedure VVOM(var a:OM);

 

begin

Объявление процедуры VVOM

M

 

end;

 

function MINOM(l:integer; a:om):real;

}

Объявление функции MINOM

begin

M

 

end;

 

begin (* Начало основной программы *)

M end.

7.4.3 Раздел операторов подпрограммы (тело ПП)

Все ранее рассмотренные операторы Паскаля могут быть использованы в разделе операторов подпрограммы. В разделе операторов функции должен обязательно присутствовать хотя бы один оператор вида

<имя функции>:=<значение>; так как после работы функции результат присваивается имени функции.

Пример 1. Полное объявление функции FACT (см. пример 1, п.7.4.2). function FACT(l:integer):integer;

var n,P:integer; begin

P:=1;

for n:=1 to l do P:=P*n;

FACT:=P

end;

Замечание. На первый взгляд, приведенную выше программу можно упростить, заменив в ней идентификатор P на FACT и сократив тем самым количество используемых переменных. Однако так делать нельзя, потому что имя функции запрещено использовать в правой части оператора присваивания и полученная таким образом программа будет содержать ошибку.

Пример 2. Приведенная ниже программа содержит ошибку ! function FACT(l:integer):integer;

var n:integer;

 

 

begin

}

Так делать нельзя:

FACT:=1;

for n:=1 to l do

имя функции запрещено использовать

fact:=fact*n

 

в правой части оператора присваивания

end;

 

 

Вразделе операторов подпрограммы можно использовать следующие данные:

1)формальные параметры; например, в функции FACT (см. пример 1 выше) используется формальный параметр "l";

2)локальные данные - это данные, которые объявлены в разделе описания подпрограммы, в основной программе локальные данные недоступны; например, в функции FACT (см. пример 1 выше) переменные "n" и "P" - локальные переменные.

136

Подпрограмма-функция fact, в теле функции оператор вида fact:=<значение> должно быть обязательно хотя бы один раз

3) глобальные данные - это данные, объявленные в разделе описаний основной программы PROGRAM.

Замечание. Может оказаться, что в вызывающем и вызываемом модуле объявлены данные, например, переменные, с одинаковым именем. Компилятор обрабатывает эти объявления автономно, поэтому можно считать, что объявлены две переменные: одна в вызывающем, другая - в вызываемом модуле. Рекомендуется избегать подобного дублирования имен, иначе в программе трудно разбираться.

7.5 СООТВЕТСТВИЕ ФАКТИЧЕСКИХ И ФОРМАЛЬНЫХ ПАРАМЕТРОВ

Итак, подпрограмма (ПП) записывается в основной программе один раз. В заголовке ПП указывается ее имя и список формальных параметров. Вызвать ПП в теле основной программы можно многократно, указав имя ПП и список фактических параметров.

При вызове подпрограммы ЭВМ производит следующие действия. Устанавливает взаимно однозначное соответствие между фактическими и формальными параметрами, то есть каждому формальному параметру ставится в соответствие фактический. Затем управление передается подпрограмме. После того, как подпрограмма проработает, управление передается вызывающей программе на оператор (для процедуры) или операнд (для функции), следующий за вызовом процедуры. Соответствие между фактическими и формальными параметрами должно быть следующим:

а) число формальных параметров должно быть равно числу фактических параметров; б) соответствующие фактические и формальные параметры должны совпадать по порядку следования и по типу; соответствующие параметры не обязательно должны быть

одинаково обозначены.

n!

(см. пример 1 из п.7.2). Запишем всю программу.

Пример 1. Вычислить p = m!(n m)!

program VP(i,o); var n,m:integer,

function fact (l:integer):integer; var P,n:integer;

begin P:=1;

for n:=1 to l do P:=P*n; fact:=P

end;

begin (* Начало основной программы *)

write ('Введите два целых неотрицательных числа n,m (n>=m): '); readen (n,m);

write ('Значение выражения: ') writeln (fact(n)/(fact(m)*fact(n-m)));

end.

Как видно на примере, подпрограмма-функция помещается после декларативных операторов программы перед "begin" программы. В объявлении функции "l" - это формальный параметр. В теле основной программы функция fact вызывается трижды (см. последний оператор writeln). При первом вызове формальному параметру l соответствует фактический параметр n. Это означает, что после того, как функция fact "запустится" (начнет работать), в ячейку l попадает значение переменной n. После окончания работы функции значение fact(n) будет вычислено. Основная программа перейдет к вычислению следующего операнда fact(m). Для этого функция fact будет вызвана второй раз, формальному параметру l теперь будет соответствовать фактический параметр m. После того, как функция проработает и выдаст значение fact(m), основная программа вызовет

137

функцию в третий раз и передаст ей фактический параметр (n-m). После того, как функция проработает и выдаст значение fact(n-m), основная программа выполнит требуемые арифметические действия и напечатает значение выражения.

Пример 2. Составим процедуру SQ решения квадратного уравнения ax2 +bx + c = 0 в предположении, что дискриминант неотрицателен (пример взят из источника /30/). Как известно,

x

= b ± d , гдеd = b2 4ac.

1,2

2a

 

С помощью этой процедуры решим квадратное уравнение

5,7y 2 - 1,2y - 8,3 = 0

program S(i,0);

 

var y1,y2:real;

(* Корни уравнения *)

procedure SQ(a,b,c:real; var x1,x2:real);

var d:real;

процедура

begin

d:=b*b-4*a*c; x1:=(-b+sqrt(d))/(2*a); x2:=(-b-sqrt(d))/(2*a)

end;

 

begin

(* Начало основной программы *)

sq(5.7,-1.2,-8.3,y1,y2); writeln(' y1=',y1,' y2=', y2)

end.

Как видно на примере, процедура помещается после декларативных операторов программы. В объявлении процедуры указано 5 формальных параметров: a,b,c - параметры-значения, предназначены для передачи исходных данных (коэффициентов квадратного уравнения) в процедуру; x1,x2 - параметры-переменные, предназначены для передачи результата (корней квадратного уравнения) из процедуры. В основной программе первым выполняется оператор вызова процедуры sq:

sq(5.7,-1.2,-8.3,y1,y2);

Здесь первые три фактических параметра 5.7,-1.2,-8.3 соответствуют формальным параметрам a,b,c, а последние два фактические параметра y1,y2 - формальным x1, x2. После того, как процедура "запустится", в ячейки a,b,c попадут числа 5.7,-1.2,-8.3, и начнут выполняться операторы d:=..., x1:=..., x2:=... .

После окончания работы процедуры управление возвратится к оператору writeln основной программы, который напечатает результат.

7.6ПАРАМЕТРЫ-ЗНАЧЕНИЯ И ПАРАМЕТРЫ-ПЕРЕМЕННЫЕ

7.6.1Если в качестве формального параметра указана переменная и ее тип, то такой параметр и есть параметр-значение.

Пример 1. Рассмотри следующий заголовок процедуры: procedure S (A:real; var B:real);

Здесь А - параметр-значение.

Для параметра-значения соответствующим фактическим параметром может быть любое выражение того же типа, что и формальный параметр. Частные случаи выражения - это константа, переменная, элемент массива, поле записи.

Пример 2. Обратиться к процедуре S из примера 1 выше можно следующим образом:

а)

S(0.5,x);

(* Здесь фактический параметр, соответствующий A - константа *)

б)

S(0.5+3*y,x); (* Здесь фактический параметр, соответствующий A - выражение *)

в)

S(r,x);

(* Здесь фактический параметр, соответствующий A - переменная *)

138

Для параметров-значений ЭВМ при вызове подпрограммы производит следующие действия: выделяет место в памяти для каждого формального параметра, вычисляет значение фактического параметра и засылает его в ячейку, соответствующую формальному параметру. На этом всякая связь между фактическим и формальным параметром-значением кончается. Таким образом, в памяти ЭВМ фактический и формальный параметр-значение занимают разные ячейки. Поэтому через параметрызначения передать в подпрограмму исходные данные можно, а передать результаты работы подпрограммы обратно - нельзя. Например, если фактический параметр есть имя переменной r (см. пример 2,в выше), то значение этой переменной r пересылается в соответствующий формальный параметр А, и на этом всякая связь между А и r кончается.

Пример 3. Распространенная ошибка - попытка передать результат из процедуры в вызываемую программу через параметр-значение.

program T(output); var i:integer;

procedure P(i:integer); begin

i:=i*2;

end;

begin (* Начало основной программы *) i:=2;

P(i),

writeln (' i=',i ) end.

В данном случае фактический и формальный параметры одинаково обозначены: "i". Но основная программа Т "знает" только одну переменную i, которая и после обращения к процедуре Р содержит число 2. Поэтому программа Т напечатает "i=2".

7.6.2. Если перед именем формального параметра стоит ключевое слово var, то такой параметр есть параметр-переменная. Действие слова var распространяется до ближайшей точки с запятой.

Пример 1. Рассмотрим следующий заголовок процедуры: procedure S(A:real; var B:real);

Здесь B - параметр-переменная.

Для параметра-переменной соответствующим фактическим параметром может быть только переменная (не константа и не выражение), а именно: скалярная переменная; массив; запись. Для некоторых компиляторов в качестве параметра-переменной нельзя передавать элемент массива.

Пример 2. Ниже приведены примеры правильного и неправильного обращение к

процедуре S из примера 1 выше:

 

S(0.5, x);

(* Корректное обращение к S:

x - переменная *)

S(0.5, 0.2+x); (* Некорректное обращение к S:

0.2+x - выражение *)

При вызове подпрограммы параметры-переменные обрабатываются так: для формального параметра используется именно та ячейка, которая содержит соответствующий фактический параметр. Поэтому параметры-переменные используются обычно для передачи результатов выполнения процедуры.

Пример 3. В Рассмотренном ниже примере процедура H изменяет оба своих формальных параметра x и y. В основной программе фактический параметр а соответствует формальному параметру-значению х, фактический параметр b - параметрупеременной y; и в основной программе после того, как проработает процедура H, значение переменной a не изменится, а значение переменной b - изменится.

program p3(i,o); var a,b:integer;

procedure H (x:integer; var y:integer); begin

x:=x+1; y:=y+1;

139

writeln (x,y) end;

begin (* Начало основной программы *) a:=0, b:=0;

H(a,b);

writeln(a,b)

end.

Результаты работы программы: ПП H напечатает "1 1", основная программа напечатает

"0 1".

7.7ЛОКАЛЬНЫЕ И ГЛОБАЛЬНЫЕ ДАННЫЕ

7.7.1Каждый модуль (программа или ПП) состоит из заголовка и блока. Пример 1. Рассмотрим процедуру P1, в которой есть вложенная процедура P2.

заголовок

блок

procedure P1(a:real; var b:real);

var k : integer; procedure p2; begin ... end;

begin

M

end;

Если блок какого-либо модуля Р1 (см. пример 1 выше) содержит внутри модуль Р2, то говорят, что Р2 вложен в Р1.

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

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

Пример 2. Рассмотрим программу nest, включающую процедуру nest1, и используемые в них идентификаторы a,b,x.

program nest; var a,b:integer;

procedure nest1; var a,x:char; begin

M

a:='!'; x:='?'; b:=b+1;

M end;

begin (* Основная программа *)

M

a:=0, b:=100; nest1;

writeln (a,b); (* На печати будет 0 101 *)

M end.

140

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]