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

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

Чем процедуры отличаются от функций

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

  1. Функции возвращают значения (а значит их вызовы можно использовать везде, где можно использовать литералы, переменные и выражения).
  2. Процедуры не возвращают данных, и потому не могут быть частью, например выражений.

Сигнатура процедур и функций

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

Сигнатура -- характеристика функции, которая говорит о том, что нужно передавать в функцию и на результат какого типа следует рассчитывать после её выполнения.
Или, если речь идёт о процедуре -- то просто "данные каких типом нужно передать в процедуру, чтобы она сработала"

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

Сигнатура процедуры определяется:

  1. Именем процедуры
  2. Числом, типом входных переменных и порядком их следования

Например, рассмотрим реализацию процедуры $sum1()$, которая складывает два числа и выводит сумму на экран:

procedure sum1(x, y: integer); // начало объявления процедуры
begin
  write(x + y);
end; // конец тела процедуры

Иллюстрацией к сигнатуре этой процедуры служит её заголовок:

procedure sum1(x, y: integer); 

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

procedure sum1(x, y: integer); // начало объявления процедуры
begin
  write(x + y);
end; // конец тела процедуры

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

  sum1(5, 7);  // вызов процедуры

end.

Вызов функции и её сигнатура

Сигнатура функции определяется:

  1. Именем функции
  2. Числом, типом входных переменных и порядком их следования
  3. Типом возвращаемого значения

Процедуры

Рассмотрим пример программы с процедурой:

 
var
  a, b, c: integer; // объявляем глобальные переменные программы
 
procedure sum(x, y: integer; var z: integer); // начало объявления процедуры
begin
  z := x + y; // тело процедуры
end;
 
begin // начало тела программы
  write('Введите два числа: ');
  readln(a, b);
  sum(a, b, c); { -- вызов процедуры с параметрами (аргументами)
  процедура вызывается своим именем,
  которое вы написали после зарезервированного слова procedure в описании}
  writeln(c);
end.

-- здесь:

  • переменная $z$ в процедуру $sum()$ передана по ссылке, это значит, что если её изменить в теле процедуре, то она изменится и в том месте, откуда её передали в процедуру (например, в теле основной программы).
  • Переменные же $x$ и $y$ переданы по значению -- это надо понимать так, что если их значения будут изменяться внутри процедуры (в данном случае), то "снаружи" эти изменения видны не будут.

Функции и псевдопеременная result

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

var
  a, b, c: integer; // глобальные переменные
 
function sum(x, y: integer): integer;
begin // начало тела функции
  result := x + y; { результат для возврата наружу 
  (в глобальное пространство программы из локального пространства функции) }
end;  // конец описания функции (её тела)
 
begin // начало тела основной программы
  readln(a, b);
  writeln(sum(a, b));
end. // конец основной программы

-- чтобы вернуть значением мы использовали так называемую псевдопеременную с именем result. (т.е. "не совсем переменную, но что-то похожее на ней")

Псевдопеременная result:

  1. Не нуждается в объявлении в секции var (локальной или глобальной)
  2. Служит для возврата из функции (возвращено будет то значение. которое вы присвоите этой переменной)

Примеры кода -- разбор решений

Пример №1 -- функция не принимающая аргументов

Задача:

Напишите функцию, которая не принимает аргументов и возвращает число $55$

Решение:

function f1():integer; // возвращает целое число 5
begin
  result := 55;  // всё просто
end;


begin // тело программы

  writeln('f1() vernula:', f1()); // вызов функции как аргумент
  readln();
end.   

-- таким образом, что вернуть какое-либо значение из функции, мы должны использовать переменную result, в примере выше именно значение из нее подставляется как аргумент writeln() после выполнения функции f1 в строке:

writeln('f1() vernula:', f1()); // вызов функции как аргумент

Пример №2 -- функция: входящие аргументы разного типа, локальные переменные подпрограммы

Задача:

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

Решение:

var m: integer;
  z : real;

function f2(a: integer; b: real): real;
var h: real; // объявим собственную (локальную) переменную функции
begin
  h := a*b - (a+b); // присваимаем результат выражения локальной переменной

  result := h; // возвращаем результат функции "наружу"

end; // конец тела функции

begin  // начало тела основной программы
  m := 2;
  z := 4.5;

  z := f2(m, z); // перезапишем z результатом работы функции

  writeln('z=', z);

  readln();
end.

Задачи для самостоятельного решения

  1. Напишите функцию, которая возвращает сумму трёх целых чисел.
  2. Напишите процедуру, которая принимает переменную целого типа по ссылке, просит пользователя ввести значение в консоли и инициализирует переменную этим значением (убедитесь, что в теле программы значение изменилось).
  3. Составьте программу, которая выводит на экран прямоугольный флаг N×M вида (с чередованием плюсов и минисов в строках):
    - - - - - -
    + + + + + +
    - - - - - -
    + + + + + +
    - - - - - -  

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

  4. Пользователь передает целое положительное число $N$, выведете на экран последовательность от $1$ до $N$ "ёлочкой", например для $N = 17$:
    1
    2 3
    4 5 6
    7 8 9 10
    11 12 13 14
    15 16 17

    ПРИМЕЧАНИЕ: для вывода очередной строки используйте отдельную подпрограмму, т.е. для каждой строки вы должны каждый раз (причем один раз для одной строки) вызывать эту подпрограмму.

Видео-пояснения

К этому уроку есть следующие видео-пояснения:

  1. Процедуры и Функции в Паскаль: отличия, возврат значения, перегрузка процедур и функций: https://youtu.be/gUr6SeA7r-E
  2. Процедуры и Функции в Паскаль: передача по ссылке и по значению. Какая разница, пример с указателем: https://youtu.be/201KCCOOtyo
  3. Ещё раз о том, что значит, что функция "возвращает значение", и другие замечания: https://youtu.be/C11m4t2Yv78

Источники и полезные материалы:

  1. Урок 13. Процедуры и функции в Pascal. Часть 2: http://learnpascal.ru/vvedenie-v-paskal/...
vedro-compota's picture

function f1(): integer;
begin
   result := 2 + 3;
end;

procedure sum(x, y: integer); // начало объявления процедуры
var h: integer;
begin
  x := x - y + f1() * 2;
  h := 8;
  writeln(x);
end;


begin // начало тела программы
    a := 1;
    b := 2;
    sum(a,  5 + 7 - f1());
    sum(b, a);


    readln();
end. 

_____________
матфак вгу и остальная классика =)

vedro-compota's picture

_____________
матфак вгу и остальная классика =)

vedro-compota's picture

  1. Понятие подпрограммы
  2. Отличие между процедурой и функцией и ситуациями их использования
  3. Передача переменных по ссылке и по значению
  4. Область видимости (в Паскаль)
  5. Когда использовать процедуру, а когда функцию ("побочный эффект" указывает что надо использовать процедуру).

_____________
матфак вгу и остальная классика =)

vedro-compota's picture

var
  a, b, c: integer; // глобальные переменные
  p: ^integer; // Тип: указатель на integer

begin

 a := 5;
 writeln('a= ', a);
 // f1(a);
 p := @a; // получаем указатель на переменную a
 writeln('p= ', p^); {смотрим что лежит в области памяти,
 на которую указывает указатель  p }

 p^ := 9; // Запись "по ссылке"
 writeln('p= ', p^);
 writeln('a= ', a);

 readln();
end. 

_____________
матфак вгу и остальная классика =)

Pages