Процедуры в Паскале

Процедуры в Паскале

Министерство образования Российской Федерации.

Северо-Кавказский Горно-Металлургический Институт (СКГТУ)

кафедра промышленной электроники .

факультет электронной техники, ПЭ-04-1 .

К У Р С О В А Я Р А Б О Т А

«

»

(вариант №9)

Выполнил Дзотцоев Лев Казгериевич

Преподаватель Яровой Иван Федорович

«___» «______________» 200__

Г. Владикавказ 2004 год

Задание

1. Приведите синтаксис описания и вызова процедуры. Опишите виды,

назначение формальных и фактических параметров. Приведите пример

описания процедуры, её вызова и поясните его.

2. Даны целые m и n. Составить программу вычисления

x = (m! +n!)/(m+n)!, где k=1x2x3x4x..xK

В программе предусмотреть:

. Ввод m и n

. Описание процедуры-функции для вычисления значения факториала :

f(k) = k! = 1x2x3x..xK

. Отображение на экране дисплея значения Х

. Комментарии в основных местах программы

2.1 Отладить и провести счет по программе.

2.2 Привести в пояснительной записке:

. Текст программы с пояснениями

. Исходные данные и результаты счета

СОДЕРЖАНИЕ

Задание

1

Содержание

2

Синтаксис описания и вызова процедуры

3

Параметры

4

Пример описания и вызова процедуры

5

Виды параметров

6

Программа

12

Пояснительная записка

13

Заключение

15

Литература

16

Приложение

17

Синтаксис описания и вызова процедуры.

Программа объемом до 10000 операторов считается малой, до 100000 операторов

– средней. Понятно, что строить такие программы непосредственно из

элементарных операции практически невозможно. Для упрощения разработки

программ в Pascal-е можно использовать подпрограммы - процедуры и функции.

Они представляют собой инструмент, с помощью которого любая программа

может быть разбита на ряд в известной степени независимых друг от друга

частей. Такое разбиение необходимо по двум причинам.

Во-первых, это средство экономии памяти: каждая подпрограмма существует в

программе в единственном экземпляре, в то время как обращаться к ней можно

многократно из разных точек программы. При вызове подпрограммы

активизируется последовательность образующих ее операторов, а с помощью

передаваемых подпрограмме параметров нужным образом модифицируется

реализуемый в ней алгоритм.

Вторая причина заключается в применении современных методов нисходящего

проектирования программ. В результате применение этих методов алгоритм

представляется в виде последовательности относительно крупных подпрограмм,

реализующих более или менее самостоятельные смысловые части алгоритма.

Подпрограммы в свою очередь могут разбиваться на менее крупные

подпрограммы, те - на подпрограммы нижнего уровня и т.д. Последовательное

структурирование программы продолжается до тех пор, пока реализуемые

подпрограммами алгоритмы не станут настолько простыми, чтобы их можно было

легко запрограммировать.

Pascal даже в сравнении с промышленными системами программирования обладает

очень мощными средствами работы с подпрограммами.

Процедуры и функции, как уже отмечалось, представляют собой относительно

самостоятельные фрагменты программы, оформленные особым образом и

снабженные именем. Упоминание этого имени в тексте программы называется

вызовом процедуры (функции). Отличие функции от процедуры заключается в

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

является некоторое единственное значение простого, строкового типа или

указателя, поэтому обращение к функции можно использовать в соответствующих

выражениях наряду с переменными и константами.

В структуре Pascal программ существует специальный раздел для

описания процедур и функций. Как известно, любое имя в программе должно

быть обязательно описано перед тем, как оно появится среди исполняемых

операторов. Не делается исключения и в отношении процедур: каждую

необходимо описать в разделе описаний.

Описать подпрограмму - это значит указать ее заголовок и тело. В

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

За заголовком следует тело подпрограммы, которое состоит из раздела

описаний и раздела исполняемых операторов. В разделе описаний процедур

могут встретиться описания процедур низшего уровня, в тех - описания других

подпрограмм и т.д.

Синтаксис и вызов (в общем) процедур:

Procedure

Uses

Label

Const

Type

Var

Begin

End;

Для выполнения процедуры необходим её вызов. Вызов осуществляется по имени

данной процедуры в теле программы. Имя процедуры воспринимается как

оператор. При его выполнении выполняется вся подпрограмма.

Описание подпрограммы состоит из заголовка и тела подпрограммы.

Заголовок

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

PROCEDURE ();

Здесь - имя подпрограммы - список формальных параметров;

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

директив ASSEMBLER, EXTERNAL, FAR, FORWARD, INLINE, INTERRUPT, NEAR}

Параметры

Параметры бывают формальные и фактические. Параметры, которые записываются

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

указывают на то, что для выполнения данной процедуры необходимы

дополнительные данные – фактические параметры.

Список формальных параметров необязателен и может отсутствовать.

{Использование процедур без параметров оправданно только в том случае, если

в них не используется обращение к глобальным переменным. Использование

таких процедур ограниченно той программой, для которой они написаны и

затруднено для других программ}.

Если же он есть, то в нем должны быть перечислены имена формальных

параметров и их тип, например:

Procedure YZ (a : real; b : integer: с : char)

Как видно из примера, параметры в списке отделяются друг от друга

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

объединять в подсписки, например, вместо

Procedure Z (а : integer; b : integer)

можно написать проще:

Procedure Z (a, b : integer)

Операторы тела подпрограммы рассматривают список формальных параметров

как своеобразное расширение раздела описаний: все переменные из этого

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

способом осуществляется настройка алгоритма подпрограммы на конкретную

задачу.

Первый формальный параметр заменяется первым фактическим, второй-вторым и

т. д.

Механизм замены формальных параметров на фактические позволяет нужным

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

следит за тем, чтобы количество и тип формальны параметров строго

соответствовали количеству и типам фактических параметров в момент

обращения к подпрограмме. Напомним: смысл используемых фактических

параметров зависит от того, в каком порядке они перечислены при вызове

подпрограммы. Пользователь должен сам следить за правильным порядком

перечисления фактических параметров при обращении к подпрограмме. Приведем

пример. рассмотрим интересующую нас часть программы (не самой удачной, но

это пока неважно) для вычисления x = (5! + 2!)/(5+2)!

Program factorial(input,output);

……

{далее нас интересует описание процедуры:}

Procedure FL(L:integer, var z: integer); {объявление процедуры, её имя ,

список формальных параметров}

Begin

Z:=1;

While L>1 do

Begin

Z:=ZxL;{тело процедуры, которая также предусматривает, что 0! и 1!

=1}

L:=l-1;

end;

end;

……..

begin

……..

{теперь рассмотрим вызов процедуры}

FL(5,a);

FL(2,b);

FL(2+5,c);

..........

end.

В данном случае l, z формальные параметры. К слову, их не надо описывать в

разделе глобальных переменных.

Фактические параметры: 5, а, 2, b, 2+5, c. В “основном” разделе VAR должны

быть описаны а, b, c

При первом вызове процедуры фактический параметр 5 заменит формальный L,

фактический a заменит формальный z, во втором 2 заменит L, b заменит z.

В третьем соответственно 2+5 заменит L, c заменит z. Для того, чтобы

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

виды формальных и фактических параметров, их назначение.

Виды параметров.

По способу передачи данных параметры можно разделить на несколько

категорий.

Любой из формальных параметров подпрограммы может быть либо параметром-

значением, либо параметром-переменной, либо параметром-константой. Если

параметры определяются как параметры-переменные, перед ними необходимо

ставить зарезервированное слово VAR, например:

Procedure tide (var a : real) Здесь параметр А - параметр-переменная.

Заголовок процедуры может быть устроен так, что некоторые группы формальных

параметров не содержат слова VAR. Например:

Procedure qwerty(a,b,c:real; var s:real);

Формальные параметры, которые входят в группы, не содержащие слова VAR,

называются формальными параметрами-значениями.

Определение формального параметра тем или иным способом существенно только

для вызывающей программы: если формальный параметр объявлен как параметр-

переменная, то при вызове подпрограммы ему должен соответствовать

фактический параметр в виде переменной определенного типа; если формальный

параметр объявлен как параметр-значение, то при вызове ему может

соответствовать произвольное выражение. Контроль за неукоснительным

соблюдением этого правила осуществляет компилятором Турбо Паскаля.

Для того чтобы понять, в каких случаях использовать параметры значения, а в

каких - параметры-переменные, рассмотрим, как осуществляется замена

формальных параметров на фактические в момент обращения к подпрограмме.

Если параметр определен как параметр-значение, то перед вызовом

подпрограммы это значение вычисляется, полученный результат копируется во

временную память и передается подпрограмме. Важно учесть, что даже если в

качестве фактического параметра указано простейшее выражение в виде

переменной или константы, все равно подпрограмме будет передана лишь копия

переменной (константы). Таким образом, назначение параметра-значения –

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

параметр-переменная, то при вызове подпрограммы передается сама переменная,

а не ее копия. Любые возможные изменения в подпрограмме параметра-значения

никак не воспринимаются вызывающей программой, так как в этом случае

изменяется копия фактического параметра, в то время как изменение параметра-

переменной приводит к изменению самого фактического параметра в вызывающей

программе. Параметр-константа схож с параметром-переменной: в подпрограмму

передается сама константа, но изменение её невозможно. Назначение такого

параметра совпадает с назначением параметра-значения . Формальные параметры-

константы указываются в заголовке программы после служебного слова const.

Его действие распространяется до ближайшей точки с запятой.

Поясним изложенное.

.....

var

a, b: integer;

......

procedure squar(a: integer; var b: integer);

begin

a:=sqr(a);

b:=sqr(b);

writeln(‘в квадрате они выглядят так: ’,a,’, ’,b);

end;

........

begin

a:=4; b:=6;

writeln(‘внимательно посмотрите на эти числа: ’, a,’, ’, b);

squar(a,b);

writeln(‘а так а не в квадрате: ’,a, ’, ’,b);

end.

Результаты выглядят так: внимательно посмотрите на эти числа: 4, 6

в квадрате они выглядят так: 16, 36

а так а не в квадрате: 4, 36

Этот пример может служить еще и иллюстрацией механизма «закрывания»

глобальной переменной а одноименной локальной: хотя переменная объявлена

как глобальная (она описана в вызывающей программе перед описанием

процедуры), в теле процедуры ее «закрыла» локальная переменная а,

объявленная как параметр-значение.

Итак, параметры-переменные используются как средство связи алгоритма,

реализованного в подпрограмме, с «внешним миром»: с помощью этих параметров

подпрограмма может передавать результаты своей работы вызывающей программе.

Разумеется, в распоряжении программиста всегда есть и другой способ

передачи результатов - через глобальные переменные. Однако злоупотребление

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

понимании и сложной в отладке. В соответствии с требованиями хорошего стиля

программирования рекомендуется там, где это возможно, использовать передачу

результатов через фактические параметры-переменные.

С другой стороны, описание всех формальных параметров как параметров-

переменных нежелательно по двум причинам. Во-первых, это исключает

возможность вызова подпрограммы с фактическими параметрами в виде

выражений, что делает программу менее компактной. Во-вторых, и главных, в

подпрограмме возможно случайное использование формального параметра,

например, для временного хранения промежуточного результата, т.е. всегда

существует опасность непреднамеренно «испортить» фактическую переменную.

Вот почему параметры-переменные следует объявлять только те, через которые

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

Чем меньше параметров объявлено параметрами-переменными и чем меньше в

подпрограмме используется глобальных переменных, тем меньше опасность

получения непредусмотренных программистом побочных эффектов, связанных с

вызовом подпрограммы, тем проще программа в понимании и отладке.

Существует одно обстоятельство, которое следует учитывать при выборе

вида формальных параметров. Как уже говорилось, при объявлении параметра-

значения осуществляется копирование фактического параметра во временную

память. Если этим параметром будет массив большой размерности, то

существенные затраты времени и памяти на копирование при многократных

обращениях к подпрограмме могут стать peшающим доводом в пользу объявления

такого параметра параметром-переменной или передачи его в качестве

глобальной переменной.

Параметры массивы и параметры строки

Может сложиться впечатление, что объявление переменных в списке

формальных параметров подпрограммы ничем не отличается от объявления их в

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

но есть одно существенное различие: типом любого параметра в списке

формальных параметров может быть только стандартный или ранее объявленный

тип. Поэтому нельзя, например, объявить следующую процедуру:

Procedure S (а : array (1..10] of real);

так как в списке формальных параметров фактически объявляется тип -

диапазон, указывающий границы индексов массива.

Если мы хотим передать какой-то элемент массива, то проблем, как

правило, не возникает, но если в подпрограмму передается весь массив, то

следует первоначально описать его тип. Например:

…...

type

mas = array [1..10] of real;

.......

PROCEDURE S (a : mas);

…...

Поскольку строка является фактически своеобразным массивом, ее передача в

подпрограмму осуществляется аналогичным образом:

.......

type

intype =string[15];

outype = string[30];

FUNCTION St (i : intype) : outype:

Требование описать любой тип-массив или тип-строку перед объявлением

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

рамках простейших вычислительных задач обычно заранее известна структура

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

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

назначения связана со значительными трудностями. По существу, речь идет о

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

«плавающими» границами изменения индексов. Например, если разработана

программа, обрабатывающая матрицу из 10 х 10 элементов, то для обработки

матрицы из 9 х 11 элементов необходимо переопределить тип, т.е.

перекомпилировать всю программу. Этот недостаток, как и отсутствие в языке

средств обработки исключительных ситуаций (прерываний), унаследован из

стандартного Паскаля и представляет собой объект постоянной и вполне

заслуженной его критики. Разработчики Турбо Паскаля не рискнули кардинально

изменить свойства базового языка, но, тем не менее, включили в него

некоторые средства, позволяющие в известной степени смягчить отмеченные

недостатки.

Прежде всего, в среде Турбо Паскаля можно установить режим компиляции,

при котором отключается контроль над совпадением длины фактического и

формального параметра-строки. Это позволяет легко решить вопрос о передаче

подпрограмме строки произвольной длины. При передаче строки меньшего

размера формальный параметр будет иметь ту же длину, что и параметр

обращения; передача строки большего размера приведет к ее усечению до

максимального размера формального параметра. Следует сказать, что контроль

включается только при передаче строки, объявленной как формальный параметр-

переменная. Если соответствующий параметр объявлен параметром-значением,

эта опция игнорируется и длина не контролируется.

Значительно сложнее обстоит дело с передачей массивов произвольной

длины. Решить эту проблему при помощи не типизированных параметров

Процедурные типы

Процедурные типы - это нововведение фирмы Borland (в стандартном Паскале

таких типов нет). Основное назначение этих типов - дать программисту гибкие

средства передачи функций и процедур в качестве фактических параметров

обращения к другим процедурам и функциям.

Для объявления процедурного типа используется заголовок процедур, в

котором опускается ее имя, например:

type

Proc = Procedure (a, b, с : real; Var d : real);

Proc2 = Procedure (var a, b);

РгосЗ = Procedure;

В программе могут быть объявлены переменные процедурных типов, например,

так:

var

р1 : Proc;

ар : array [1..N] of Proc2;

Переменным процедурных типов допускается присваивать в качестве значений

имена соответствующих подпрограмм. После такого присваивания имя переменной

становится синонимом имени подпрограммы.

В отличие от стандартного Паскаля, в Турбо Паскале разрешается

использовать в передаваемой процедуре как параметры-значения, так и

параметры-переменные.

Нетипизированные параметры-переменные

Еще одно и очень полезное нововведение фирмы Borland - возможность

использования нетипизированных параметров. Параметр считается

нетипизированным, если тип формального параметра-переменной в заголовке

подпрограммы не указан, при этом соответствующий ему фактический параметр

может быть переменной любого типа. Заметим, нетипизированными могут быть

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

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

данных несущественен. Такие ситуации чаще всего возникают разного рода

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

очень удобно использовать для передачи подпрограмме одномерных массивов

переменной длины.

Параметры- сложные типы данных

Рассмотрены прежде категории параметров не исчерпывают всех вопросов

передачи информации в Pascal-e. Использование в качестве параметров сложных

типов данных имеет свои особенности.

Рассмотрим массивы и строки открытого типа. Открытый массив (строка) –

массив (строка) без указания типа индекса (размера массива(строки)).

Пример:

Procedure getfive(var massiv: array of real);

В данном случае вместо формального параметра может использоваться любой

массив с элементами типа real. Индексация элементов открытого массива

всегда начинается с нуля. Такие массивы введены для того, чтобы

подпрограмма могла обрабатывать массивы любого размера.

Программа вычисления x=(m!+n!)/(m+n)!, где m, n целые (неотрицательные)

program factorial_(input,output); {название программы}

label 0; {описываем метку}

var

rez:real;

m,n:longint; {описали глобальные переменные, используемые в программе}

function fact(z: longint): real; {заголовок функции с формальным параметром-

значением, типом}

var

y: real; {описали локальную переменную}

begin

y:=1; {для получения результата необходимо присвоить у значение 1. также

при помощи этого реализуется вычисление 0! и 1!}

while z>1 do {запускаем цикл в обратную сторону, для упрощения опустим

множитель 1}

begin

y:=y*z;

z:=z-1

end;

fact:=y{вычисляем факториал, присваиваем его значение функции}

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

begin{начало тела программы}

writeln('введите неотрицательные числа'); {для удобства пользователя просим

ввести числа}

0:readln(m,n); {в память вводятся числа}

if m or n 1 do запускаем цикл в обратную сторону, т. к. результат получается

один и тот же, но при этом не приходится описывать дополнительную локальную

переменную для запуска цикла с параметром. 1 исключаем из вычисления

факториала по вышеуказанным причинам.

begin

y:=y*z;

z:=z-1

end;

fact:=y этим оператором присваиваем функции значение факториала.

Точку с запятой перед end можно не ставить.

end; конец функции

begin начало тела программы

writeln('введите неотрицательные числа'); данный оператор выводит на экран

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

0:readln(m,n); при помощи этого оператора ввода информации исходные данные

заносятся в ячейки памяти.

if m or n <0 then begin writeln(‘вы ошиблись, вводите неотрицательные

числа’);

goto 0

end; если пользователь все же ввел отрицательные числа, то программа выдаст

неверный результат, данная последовательность операторов выводит на экран

сообщение об ошибке пользователя и возвращает к вводу чисел

rez:=(fact(m)+fact(n))/fact(m+n); вычисляем значение (m!+n!)/(m+n)!

writeln('результат: ',rez) данный оператор вывода информации выводит на

экран вычисленное значение.

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

Приведем для пущей надежности еще несколько результатов счета

M=2 N=8 X=1.1111662257Е-02

M=4 N=4 X=1.1904761905Е-03

M=0 N=3 X=1.1666666667Е+00

M=3 N=15 X=2.0424836601Е-04

ЗАКЛЮЧЕНИЕ

Система программирования Турбо Паскаль содержит мощный инструмент

разработки программ – подпрограммы. В данной курсовой приведены синтаксис

процедур, виды и назначение параметров. Как мы увидели, программа

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

та же программа без процедур-функций. Использование процедур-функций отнюдь

не является дурным тоном в программировании, поэтому каждый изучающий язык

программирования Паскаль должен обязательно иметь представление о

процедурах-функциях и уметь ими пользоваться.

Литература

А. Масюков. Краткий конспект лекций по информатике.

Интерактивный учебник Turbo Pascal 7.0

С. А. Абрамов. Начала программирования на языке паскаль

Приложение

ASSEMBLER - эта директива отменяет стандартную последовательность

машинных инструкций, вырабатываемых при входе в процедуру и перед выходом

из нее.

EXTERNAL - с помощью этой директивы объявляется внешняя подпрограмма.

FAR - компилятор должен создавать код подпрограммы, рассчитанный на дальнюю

модель вызова. Директива NEAR заставит компилятор создать код, рассчитанный

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

генерируются с расчетом на дальнюю модель вызова, а все остальные

подпрограммы - на ближнюю модель.

В соответствии с архитектурой микропроцессора ПК, в программах могут

использоваться две модели памяти: ближняя и дальняя. Модель памяти

определяет возможность вызова процедуры из различных частей программы: если

используется ближняя модель, вызов возможен только в пределах 64 Кбайт (в

пределах одного сегмента кода, который выделяется основной программе и

каждому используемому в ней модулю); при дальней модели вызов возможен из

любого сегмента. Ближняя модель экономит один байт и несколько микросекунд

на каждом вызове подпрограммы, поэтому стандартный режим компиляции

предполагает эту модель памяти. Однако при передаче процедурных параметров

соответствующие подпрограммы должны компилироваться с расчетом на

универсальную - дальнюю модель памяти, одинаково пригодную при любом

расположении процедуры и вызывающей ее программы в памяти.

Явное объявление модели памяти стандартными директивами имеет более

высокий приоритет по сравнению с настройкой среды.

FORWARD - используется при опережающем описании для сообщения компилятору,

что описание подпрограммы следует где-то дальше по тексту программы (но в

пределах текущего программного модуля).

INLINE - указывает на то, что тело подпрограммы реализуется с помощью

встроенных машинных инструкций.

INTERRUPT - используется при создании процедур обработки прерываний

опережающее описание:

Procedure В (j : byte);

forward;

Procedure A (i : byte);

begin

B(i);

End;

Procedure B;

Begin

…………….

A(j);

End;

Как видим, опережающее описание заключается в том, что

объявляется лишь заголовок процедуры В, а ее тело заменяется стандартной

директивой FORWARD. Теперь в процедуре А можно использовать обращение к

процедуре В - ведь она уже описана, точнее, известны ее формальные

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

Обратите внимание: тело процедуры В начинается заголовком, в котором уже не

указываются описанные ранее формальные параметры.

Модуль – самостоятельная программная единица, ресурсы которой могут быть

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

другим типом - .tpu);