Процедуры в Паскале
Процедуры в Паскале
Министерство образования Российской Федерации.
Северо-Кавказский Горно-Металлургический Институт (СКГТУ)
кафедра промышленной электроники .
факультет электронной техники, ПЭ-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);