Процедуры: выносим повторяющийся код

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

Процедура — это именованный кусок программы (подпрограмма), который можно вызывать сколько угодно раз по имени.

Зачем разбивать программу на части

Чем больше программа, тем труднее держать её в голове целиком. Представьте книгу без глав — сплошной текст на тысячу страниц. Невозможно читать! Поэтому книги делят на главы, а программы — на подпрограммы. Подпрограмма решает одну небольшую задачу, у неё есть имя, и её можно вызывать из разных мест. Это даёт три огромных преимущества:

  • Нет повторов. Написали один раз — вызываете многократно. Не нужно копировать один и тот же код.
  • Понятность. Программа из вызовов НарисоватьРамку, ВвестиДанные, Посчитать читается как план, а не как каша из команд.
  • Удобство правок. Нашли ошибку — исправили в одном месте, и она исчезла везде.

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

Простейшая процедура

Процедуру описывают до основного begin программы, словом procedure:

procedure Privet;        // объявление процедуры
begin
  writeln('========');
  writeln('Привет!');
  writeln('========');
end;

begin                    // основная программа
  Privet;                // вызов процедуры
  Privet;                // и ещё раз
end.

Здесь мы один раз описали процедуру Privet, а в основной программе вызвали её дважды — просто написав имя. Каждый вызов выполняет всё тело процедуры. Обратите внимание: у процедуры своё begin...end, которое завершается точкой с запятой (а не точкой — точка только у самой программы). Запустите аналог на Python (там подпрограммы объявляют через def):

def privet():
    print('========')
    print('Привет!')
    print('========')

privet()
privet()

Вывод:

========
Привет!
========
========
Привет!
========

Параметры: передаём данные в процедуру

Процедура из примера выше всегда делает одно и то же. Чтобы она была гибкой, ей передают параметры — данные, с которыми она работает. Параметры объявляют в скобках после имени, указывая их типы:

procedure Ramka(text: string);   // параметр text
begin
  writeln('+-----------+');
  writeln('| ', text);
  writeln('+-----------+');
end;

begin
  Ramka('Заголовок');    // передаём разные значения
  Ramka('Меню');
end.

Теперь процедура Ramka рисует рамку вокруг любого текста, который ей передали. Имя text внутри процедуры — это параметр: при вызове он получает переданное значение. Можно передавать несколько параметров через точку с запятой: procedure Summa(a, b: integer). Запустите аналог:

def ramka(text):
    print('+-----------+')
    print('|', text)
    print('+-----------+')

ramka('Заголовок')
ramka('Меню')

Вывод:

+-----------+
| Заголовок
+-----------+
+-----------+
| Меню
+-----------+

Локальные и глобальные переменные

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

procedure Schyot;
var
  i: integer;          // локальная переменная процедуры
begin
  for i := 1 to 3 do
    write(i, ' ');
  writeln;
end;

Здесь i «живёт» только внутри Schyot. Это очень хорошо: процедура не мешает остальной программе, и наоборот. Аналогия: локальные переменные — как черновик, который вы выбрасываете после решения задачи; он не загромождает рабочий стол. Правило хорошего тона: используйте локальные переменные везде, где можно, и избегайте лишних глобальных — так программа надёжнее, ведь части не влияют друг на друга случайно.

Попробуй сам

Напишите процедуру Liniya(n), которая печатает строку из n звёздочек. Вызовите её несколько раз с разными значениями, чтобы получить «лесенку». Проверьте на Python:

def liniya(n):
    print('*' * n)

liniya(3)
liniya(5)
liniya(7)

Вывод:

***
*****
*******

Частые ошибки

  • Объявили процедуру после begin. Все процедуры описывают до основного begin программы, иначе среда их не увидит.
  • Точка вместо точки с запятой. Тело процедуры завершается end; с точкой с запятой; точка ставится только в самом конце программы.
  • Тип параметра не указан. В скобках у параметра обязательно указывают тип: (text: string), а не просто (text).
  • Чрезмерное использование глобальных переменных. Старайтесь работать с локальными переменными и параметрами — так меньше неожиданных связей между частями программы.

Итоги

  • Процедура — подпрограмма, выполняющая действие; описывается словом procedure до основного begin и вызывается по имени.
  • Вынос кода в процедуры убирает повторы, делает программу понятнее и упрощает правки.
  • Параметры (в скобках, с указанием типа) передают процедуре данные, делая её универсальной.
  • Локальные переменные видны только внутри процедуры; глобальные — во всей программе.
  • Предпочитайте локальные переменные и параметры — это делает программу надёжнее.
Проверьте себя
1. Где в программе нужно описывать процедуры?
AПосле основного begin
BДо основного begin программы
CВнутри основного begin...end
DПосле end. в конце программы
2. Для чего процедуре нужны параметры?
AЧтобы ускорить программу
BЧтобы передавать в неё разные данные и делать её универсальной
CЧтобы объявить глобальные переменные
DПараметры обязательны для любой процедуры
3. Где видна локальная переменная, объявленная внутри процедуры?
AВо всей программе
BТолько внутри этой процедуры
CТолько в основном begin
DВ других процедурах
Поддержать проект