Функции и процедуры в языке программирования Паскаль

СОДЕРЖАНИЕ

  Стр.
1. Методические указания…………………………………………………………
1.1. Цель работы………………………………………………………………….
1.2.Функции в языке программирования Си……....…………………………..
1.2.1.Функции и их определение……………………………………………..
1.2.2. Функции без параметров……...………………………………………...
1.2.3. Функции с параметрами…….………………………………………….
1.3. Функции и процедуры в языке программирования Паскаль……………..
1.3.1. Определение подпрограмм–процедур и подпрограмм–функций...….
1.3.2. Описание подпрограммы–процедуры………………………………....
1.3.3. Описание подпрограммы–функции…………………………………....
2. Задания к лабораторной работе………………………………………………...
Библиографический список………………………………………………………..

 

МЕТОДИЧЕСКИЕ УКАЗАНИЯ

Цель работы

 

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

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

Функции в языке программирования Си

Функции и их определение

Функция представляет собой самодостаточную единицу программного кода, разработанную для решения конкретной задачи. Функция в языке Си играет ту же роль, какую играют функции и процедуры в других языках программирования, хотя в деталях эти роли могут быть различными. В результате выполнения некоторых функций происходит то или иное событие. Например, в результате выполнения функции printf() на вашем экране появляются конкретные данные. Другие функции возвращают значения для их последующего использования в программе. Например, функция strlen() сообщает программе длину заданной строки. В общем случае функция может одновременно выполнять действия и возвращать значения.

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

Многие программисты предпочитают думать о функции как о “черном ящике”, представленном в терминах информации, которая поступает на вход этого ящика (ввод), и значением или действием, которое он производит (вывод). Вас не должно интересовать, что происходит внутри черного ящика, если, конечно, вы не программист, занимающийся разработкой этой функции. Например, когда вы используете функцию printf(), вы знаете что ей нужно передать управляющую строку и, возможно, некоторые аргументы. Вы также знаете, какой выход должна генерировать функция printf(). Вам не нужно знать программный код реализации функции printf(). Такой подход к использованию функций позволяет сосредоточить все усилия на создании общей структуры программы и не отвлекаться на отдельные детали.

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

Что вы должны знать о функциях?

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

 

Функции без параметров

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

#include <stdio.h>

void good(void);

void fine(void);

int main(void)

{

good();

good();

fine();

return 0;

}

void good(void)

{

printf("Наш институт очень хороший!\n");

}

 

void fine(void)

{

printf("Наш институт лучше всех!\n");

}

Выходные данные будут иметь следующий вид:

Наш институт очень хороший!

Наш институт очень хороший!

Наш институт лучше всех!

Функция good() трижды появляется в рассматриваемой программе. В первый раз она появляется в виде прототипа void good(void), передающего компилятору информацию о функциях, которые будут использованы в данной программе. Во второй раз она появляется в основной функции main() в форме вызова функции good(). Причем вызов осуществляется дважды. И, наконец, в данной программе представлено определение функции, которое является исходным кодом самой функции:

void good(void)

{

printf("Наш институт очень хороший!\n");

}

Прототип – это форма объявления, которая уведомляет компилятор о том, что вы используете конкретную функцию. Он также определяет свойства этой функции. Например, первое ключевое слово void в прототипе функции good() указывает на то, что функция good() не имеет возвращаемого значения. В общем случае, функция может возвратить значение в вызывающую функцию для последующего его использования, но функция good() этого не делает. Второе void, то что находится в скобках за именем функции good(void), означает, что функция не принимает аргументов.

Обратите внимание, что ключевое слово void употребляется в смысле “пусто”, а не в смысле “неправильно”.

Функция fine() также трижды появляется в рассматриваемой программе. В основной функции main() она вызывается один раз.

Как же работает программа?

Сначала в основной функции main() осуществляется первое обращение к функции good(). Программа переходит к выполнению этой функции. В результате на экране появляется сообщение:

Наш институт очень хороший!

Затем осуществляется возврат в основную функцию main(), в которой осуществляется повторный вызов функции good(). В результате работы этой функции на экране появляется второе сообщение:

Наш институт очень хороший!

После возврата в основную функцию main() происходит вызов функции fine(), в результате работы которой на экране появляется сообщение:

Наш институт лучше всех!

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

Функции с параметрами

Функции, возвращающие одно значение

 

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

#include <stdio.h>

#include <conio.h>

int sign(int a);

int main(void)

{

int x,y,z;

clrscr();

printf("Введите x=");

scanf("%d",&x);

printf("Введите y=");

scanf("%d",&y);

z=sign(x)+sign(y)+sign(x+y);

printf("z=%d",z);

getch();

return 0;

}

int sign(int a)

{

int ss;

if (a<0)

ss=-1;

else

if (a==0)

ss=0;

else

ss=1;

return ss;

}

В данной программе вычисляется выражение: z(x)=sign(x)+sign(y)+sign(x+y).

Переменные x и y вводятся с клавиатуры. Функция sign() определяется следующим выражением:

sign(a)=

Определение функции начинается с описания ее прототипа: int sign(int a). Эта строка сообщает компилятору, что функция sign() имеет один аргумент целого типа int a. Этот аргумент называется входным формальным параметром. Подобно переменным, определенным внутри функции, формальные параметры представляют собой локальные переменные, действующие в рамках только данной функции.

Когда функция принимает аргументы, ее прототип задает их количество и типы, при этом употребляются списки по типам, в которых имена переменных отделяются друг от друга запятыми. Например, double func(double a, double b, int c). При желании имена переменных можно опустить в прототипе. Например в нашем случае, можно записать: int sign(int ).

Первое ключевое слово int в прототипе int sign(int a) означает, что значение переменной, которое функция возвращает в основную функцию main() целого типа. Возврат осуществляется в точку вызова функции.

Значение переменной аназначается с помощью фактического аргумента в вызове функции sign().

В строчке программы z=sign(x)+sign(y)+sign(x+y) три раза происходит обращение к функции sign(). При первом обращении фактическим аргументом является переменная х, при втором – у, при третьем – х+у. При каждом обращении значению формального параметра присваивается значение фактического параметра, т.е. при первом обращении переменной априсваивается значение х, при втором переменной априсваивается значение у, при третьем обращении переменной а присваивается значений х+у.

Таким образом передается информация из вызывающей функции в вызываемую. В данной программе из основной функции main() информация передается в функцию sign(). Чтобы передать информацию в противоположном направлении, используется возвращаемое значение, которое передается из вызываемой функции в вызывающую с помощью оператора return. Ключевое слово return обеспечивает то, что следующее за ним значение переменной становится возвращаемым значением функции. Возвратить с помощью return можно только одно значение переменной. В рассматриваемом случае функция sign() возвращает значение, присвоенное переменной ss. Поскольку ssимеет тип int, следовательно, функция sign() также имеет этот тип.

Функции, возвращающие несколько значений

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

#include <stdio.h>

#include <conio.h>

void fff(int, int, int*summa,int*raznost);

int main(void)

{

int x,y,sum,razn,i;

clrscr();

for (i=0;i<4;i++)

{

printf("Введите x=");

scanf("%d",&x);

printf("Введите y=");

scanf("%d",&y);

fff(x,y,&sum,&razn);

printf("sum=%d ",sum);

printf("razn=%d ",razn);

printf("\n");

};

getch();

return 0;

}

void fff(int a,int b, int *summa,int *raznost)

{

*summa=a+b;

*raznost=a-b;

}

 

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

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

Указатели

Указатель представляет собой адрес, по которому хранится соответствующая переменная [1,2].

Унарная операция & выдает адрес, по которому хранится соответствующая переменная.

Если рр является именем переменной, то &рр является адресом, по которому хранится переменная. Адрес можно представить как некоторую ячейку в памяти.

Предположим, что имеется оператор: рр=24.

Предположим, что адрес, по которому хранится переменная рр, выглядит следующим образом: ОВ76(адреса задаются в шестнадцатеричной форме).

Тогда оператор printf(“%d %p\n”,pp,&pp) выводит следующие значения:

24 ОВ76.

Для описания переменной, в которой хранится указатель, используется специальный тип.

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

Тип указатель задается следующим образом:

int *ptr; /* *ptr указатель на целочисленную переменную, т.е. адрес целочисленной переменной*/

char *pc; /* *pc указатель на символьную переменную*/

float *pf,*pg; /* *pf и *pg указатели на вещественные переменные*/

Рассмотрим следующий пример:

nurse=22;

ptr=&nurse;

val=*ptr;

В данном примере переменной nurse присваивается значение 22. Затем переменной ptr, которая описана как указатель, присваивается значение адреса nurse. Третья производимая операция называется операцией разыменования, или операцией снятия косвенности, т.е. переменной val присваивается значение, хранящееся по адресу ptr. В конечном итоге переменная val получает значение 22.

Теперь посмотрим как работает программа, использующая функцию, возвращающую два значения. Вызов функции имеет вид: fff(x,y,&sum,&razn).

Переменные x и y являются входными фактическими параметрами. Они передаются из основной функции main() в функцию fff() и замещают своими значениями формальные параметры a и b. Для передачи параметров sum и razn, которые являются выходными, используются не их значения, а их адреса. Это означает, что формальные аргументы summa и raznost, появляющиеся в прототипе и определении функции fff(), используют адреса в качестве своих значений. В силу этого они должны быть объявлены как указатели. Поскольку переменные sum и razn целого типа, summa и raznost указатели на целые значения, то описание функции должно выглядеть следующим образом:

void fff(int a,int b, int *summa,int *raznost).

Тело функции fff() содержит два следующих оператора:

*summa=a+b;

*raznost=a-b;

Эти операторы являются операторами снятия косвенности, т.е. по адресу переменной summa записывается значение a+b, а по адресу переменной raznost записывается значение a-b.

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

В следующем примере в качестве аргумента используется массив чисел. В основной программе вводится количество элементов массива mas. Затем с помощью функции vvod() осуществляется заполнение массива элементами. Вывод элементов массива происходит в основной программе. Для передачи массива используется указатель, в котором хранится адрес первого элемента массива.

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

void vvod(int*,int);

int main(void)

{

int n,i;

int mas[20];

clrscr(); randomize();

printf("Введите количество элементов в массиве n=");

scanf("%d",&n);

vvod(&mas[0],n);

printf("\n");

for (i=0;i<n;i++)

printf("%d ",mas[i]);

getch();

return 0;

};

void vvod(int *mass,int nn)

{

int ii;

printf("Количество элементов в массиве равно \n",nn);

for (ii=0;ii<nn;ii++)

{

mass[ii]=random(12);

}

}

В функции ввода осуществляется заполнение массива с помощью генератора случайных чисел. Если необходимо заполнение осуществлять с помощью ввода с клавиатуры, то используется следующий оператор: scanf("%d",&mass[ii]).

 

Функции и процедуры в языке программирования Паскаль

1.3.1. Определение подпрограмм–процедур и подпрограмм–функций

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

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

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

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

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

· стандартные процедуры и функции языка Паскаль;

· процедуры и функции определенные пользователем.

Впрочем, то же самое можно сказать и о функциях языка Си.

К стандартным функциям относятся функции: abs(x), sin(x), cos(x), exp(x), round(x) и многие другие. К стандартным процедурам: dec(x,n) – уменьшает значение целочисленной переменной x на n. Если n отсутствует, то уменьшает значение x на 1. Inc(x,n) - увеличивает значение целочисленной переменной x на n. Если n отсутствует, то увеличивает значение x на 1. С полным перечнем стандартных процедур и функций можно ознакомиться в справочниках по программированию на языке Паскаль.

Пользователь может создавать свои процедуры и функции. Для этого он должен описать процедуру или функцию в разделе описания процедур и функций. Затем там, где это необходимо, вызвать процедуру (функцию). Прототипирование процедур и функций в языке Паскаль не требуется.

 

1.3.2. Описание подпрограммы–процедуры

Описание процедуры включает заголовок и тело процедуры. Заголовок состоит из зарезервированного слова procedure, имени процедуры и, заключенного в скобки, списка формальных параметров с указанием типа. Название «формальные» эти параметры получили в связи с тем, что в этом списке заданы только имена для обозначения исходных данных и результатов работы процедуры, а при вызове подпрограммы на их место будут поставлены конкретные значения, которые называются фактическими параметрами. Механизм формальных – фактических параметров обеспечивает механизм замены, который позволяет выполнять процедуру с различными данными. Между фактическими параметрами в операторе вызова процедуры и формальными параметрами в заголовке процедуры устанавливается взаимно-однозначное соответствие. Количество, типы и порядок следования формальных и фактических параметров должны совпадать.

Тело процедуры – блок, по структуре аналогичный программе.

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

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

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

Можно выделить два класса формальных параметров:

1) параметры-значения;

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

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

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

Общий вид описания процедуры имеет вид:

Procedure <имя> (список формальных параметров, блок описания);

Const …; ù

… ý блок описания

Var ….; û

begin

<операторы>

end;

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

<имя> (<список фактических параметров>);

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

Рассмотрим пример программы с использованием процедур:

 

Program Prog;

Uses Crt;

Type vector=array[1..9] of real;

Var Y,Z:vector;

j: integer;

M,D,S:real;

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

Procedure Zap_mas(Var X:vector; n:integer);

begin

for j:=1 to 9 do

X[j]:=random;

end;

{ Процедура вывода массива }

Procedure Vivod(X:vector; n:integer);

begin

for j:=1 to 9 do

write( X[j]:4:2);

writeln;

end;

{ Процедура вычисления математического ожидания, дисперсии и среднеквадратического отклонения }

Procedure Mat_Disp(X:vector;Var Mat,Disp,Sro:real);

begin

{Мат. ожидание}

Mat:=0.0;

for j:=1 to 9 do Mat:=Mat+X[j];

Mat:=Mat/9;

{Дисперсия}

Disp:=0.0;

for j:=1 to 9 do Disp:=Disp+SQR(X[j]-Mat);

Disp:=Disp/9;

{Среднеквадратичное отклонение}

Sro:=SQRT(Disp)

end;

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

Begin

ClrScr;

Zap_mas (Y,9);

Zap_mas (Z,9);

Mat_Disp(Y,M,D,S);

Vivod(Y,9);

writeln(' M= ',M:6:4, ' D=',D:6:4,' S=',S:6:4);

Mat_Disp(Z,M,D,S);

Vivod(Z,9);

writeln(' M= ',M:6:4, ' D=',D:6:4,' S=',S:6:4);

writeln('Для выхода из программы нажмите любую клавишу');

readkey;

end.

 

Данная программа с помощью процедурыZap_mas()формирует массивы Y и Z,состоящие из 9случайных чисел. Формирование происходит с помощью генератора случайных чисел.

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

Procedure Zap_mas(Var X:vector; n:integer).

Формальными параметрами для данной процедуры являются массив X и его размерность n. Формальный массив X имеет такой же тип, как и фактические массивы Y и Z, которые передаются в данную процедуру для заполнения. В заголовке процедуры перед формальным параметром X стоит служебное слово Var. В данном случае это означает, что массив X является и входным и выходным параметром одновременно. Формальный параметр n является входным параметром. Его значение в теле процедуры не меняется.

Для заполнения двух массивов программа два раза обращается к процедуре Zap_mas(), посылая туда соответствующие фактические параметры:

Zap_mas (Y,9);

Zap_mas (Z,9);

Далее программа использует процедуруMat_Disp(), в которой вычисляется математическое ожидание (Mx), дисперсия (Dx), и среднеквадратическое отклонение sx случайной величины X:

.

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

Procedure Mat_Disp(X:vector; Var Mat,Disp,Sro:real).

Mассив X является формальным входным параметром. Параметры Mat, Disp, Sro являются формальными выходными параметрами, поэтому перед ними стоит служебное слово Var.

После формирования массивов программа обращается к процедуре вычисления математического ожидания, дисперсии и среднеквадратического отклонения, посылая туда фактический входной параметр Y и принимая назад в основную программу фактические выходные параметры M,D,S. Обращение к процедуре имеет вид: Mat_Disp(Y,M,D,S). Затем программа обращается к процедуре Vivod(), в которой осуществляется вывод, сформированного массива Y: Vivod(Y,9). Параметры процедуры являются входными, так как вывод элементов массива осуществляется в теле процедуры. Назад в основную программу информация не передается. Значения M, D, S для массива Y печатаются в основной программе.

Затем те же действия осуществляются для массива Z:

Mat_Disp(Z,M,D,S);

Vivod(Z,9);

writeln(' M= ',M:6:4, ' D=',D:6:4,' S=',S:6:4);

 

1.3.3. Описание подпрограммы–функции

Подпрограмма–функция обрабатывает данные, переданные ей из главной программы, и затем возвращает полученный результат. Функция, определенная пользователем, состоит из заголовка и тела функции. Заголовок содержит зарезервированное слово Function, имя, список формальных параметров (заключенный в скобки) и тип возвращаемого функцией значения. Тело функции представляет собой локальный блок, по структуре сходный с программой. Общий вид описания функции:

Function <имя> (<параметры>): <тип результата>;

Const …; ù

… ý блок описания

Var ….; û

begin

<операторы>

end;

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

Рассмотрим пример, использующий подпрограмму–функцию.

Program func:

Uses Crt;

Var rez:real; m,n,mn1:integer;

Function Fact(l:integer):integer;

Var i,p:integer;

begin

i:=1;

p:=1;

while i<=l do

begin

p:=p*i;

i:=i+1

end;

Fact:=p;

writeln ('Fact=', p)

end;

Begin {Основная программа}

ClrScr;

Write('Введите значение n=');

Readln(n);

Write('Введите значение m=');

Readln (m);

mn1:=n+m;

rez:=(Fact(n)+Fact(m))/Fact(mn1);

writeln ('Результат равен rez=',rez:5:2);

writeln ('Для выхода из программы нажмите Enter');

readln

end.

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

Для вычисления m!, n! и (m+n)! используется функция Fact().

Заголовок функции имеет следующий вид: Function Fact(l:integer):integer.

Переменная l целого типа является формальным входным параметром. Имя функции Fact является выходным параметром. Выходной параметр также целого типа. В теле функции имени функции присваивается результат вычисления факториала. В основной программе три раза происходит обращение к подпрограмме Fact(): rez:=(Fact(n)+Fact(m))/Fact(mn1). В первый раз в качестве фактического входного параметра используется значение переменной n, второй раз – значение переменной m, в третий раз – значение переменной mn1= m+n.