Функции и процедуры

Мы начинаем знакомиться с более продвинутой моделью программирования. До этого мы старались изучить некоторые основы, принципы выполнения программ, простейшие алгоритмы осуществления задач. Все наше выполнение программы в основном сводилось к модели сверху вниз без всяких "поворотов" (исключение циклы). В более-менее серьезных программах, акценты чаще делаются на процедурное программирование. Хотя есть и другие модели программирования, которые определенно выше классом, взять хотя бы ООП (объектно-ориентированное программирование) Под термином (процедурное программирование) в данном случае, я имею ввиду: возможность создавать отдельные полезные блоки кода, которые вызываются нашей программой в любое, нужное для осуществления ее задач время. Более того, из любого места в нашем коде! Под это правило больше всего подходят процедуры и функции. Принцип такой модели:


 


Eсли у вас по каким то причинам не показывает ролик, можно скачать и просмотреть локально любым Flash плеером. На флеш видео выше я расположил два блока:

  • Основной блок
  • Вызываемый (процедура или функция)

До этой статьи мы писали только в одном основном блоке кода. Постепенно получая навыки программирования, вы будете осознавать, что чем выше ваш уровень, тем меньше кода вы пишете в основном блоке и больше в вызываемых блоках, то есть в процедурах или функциях. В данном случае применяя слово ИЛИ, я не имел ввиду что процедуры и функции это одно и тоже. Хотя их функциональное различие только в том, что процедура не возвращает никаких значений из своего блока при завершении, а функции возвращают, но только одно значение, которое может быть: адресом: переменной , массива, функции и прочего просто каким-то значением, например число 5 Обратите внимание на последовательность выполнения инструкций команд в видео. Как вы заметили наверно, функцию или процедуру нужно вызвать и после того, как она отработает, она возвращает управление основному блоку кода на строку, идущую сразу за той, с которой мы ее вызвали. Более того, вы надеюсь заметили, что мы ее вызвали 2 раза из разных нужных нам мест. Хотя ее можно вызвать столько раз , сколько требуется. То что на видео, можно легко реализовать с помощью меток и команды Goto. Однако такой подход сделает ваш код уродливым и плохо читаемым. Именно поэтому, данную команду почти не применяют. Более того, даже отказались от подобия этого: так называемых подпрограмм (Gosub Return), которые вы возможно еще где то встретите в старых исходных текстах программ. Но давайте вернемся к процедурам и функциям. Они тоже состоят из блоков. Ниже лишь схематичное представление:

Процедура:

Sub имя процедуры (1 параметр, 2 параметр, и так далее сколько требуется)
     1 команда
     2 команда
     3 команда
     4 команда
       ......
       ......
End Sub

Функция:

Function имя функции  (1 параметр, 2 параметр, и так далее ) As  Integer  
     1 команда
     2 команда
     3 команда
     4 команда
      ......
      ......   
     Return 10
End Function

  • В начале идет команда объявления :
    • Sub - если объявляем процедуру
    • Function  - если объявляем функцию
  • Далее следует имя функции или процедуры. Правила для имен функций или процедур ничем не отличаются от правил для имен переменных, массивов, комментариев. Если пропустили, читаем первые статьи про переменные. 
  • Далее в скобках идет необходимый нам список параметров (с их типами), которые могут понадобится функции или процедуре. Хотя можно не указывать ни одного параметра, все зависит от задачи, которую выполняет функция или процедура
  • Далее в этой строчке только для функции указывается тип значения, которое функция будет возвращать (у нас она возвращает тип Integer).
  • На следующих строчках идет тело функции или процедуры, в котором могут быть любые команды. И среди них для функции, после команды Return нужно указать то, что требуется возвратить из функции.
  • Завершается блок двумя командами, совмещенными в одну:
    • End Sub  - для процедуры 
    • End Function  - для функции

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

Sub My( a As Byte )
    Print a^2
End Sub

My(1)
My(2)
My(3)
Sleep


В примере мы объявили процедуру с именем My. Она принимает один параметр с типом байт  (a as byte) .  В теле процедуры одна команда Print, выводящая на экран вычисление параметра a, возведенного в степень двойки.

Для вызова процедуры достаточно просто использовать ее имя. И уж если мы указали один параметр, то и его тоже следует указать в скобках. Мы вызвали процедуру три раза с разным параметром. В итоге на экране отобразились различные вычисления ее работы. Вы уже поняли, что циферки 1,2,3 которые мы по очереди посылаем в скобках, присваиваются  параметру  a  процедуры. И процедура попросту берет этот параметр и использует в своем теле в данном случае для вычислений.

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

Плеер (Макаревич )
Плеер (Киркоров)

 и так далее...   :)

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

Sub My( a As Integer )
Print a^2
End Sub

Dim a As Integer=55
My(a)
Print a
Sleep


Помимо процедуры, мы объявили переменную 'a' в основном коде. Однако в процедуре мы вроде как производим с переменной математические действия, и это подтверждает нам команда Print, которая выводит результат 3025.  Но далее, уже после того, как отработала процедура, мы снова заставляем программу печатать то, что находится в переменной 'а' . Как видно она не изменилась и равна 55. В реале переменная 'а' в коде и переменная 'а' в процедуре-это две разные переменные, находящиеся в разных местах памяти компьютера. В следующей статье, мы рассмотрим все области видимости переменных в программе.

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

Function My ( a As Byte ) As Byte
    a=a^2
    Return a
End Function

Dim a As Byte=5
a=My(a)
Print a
Sleep


Здесь мы отправляем в функцию число 5. Далее производятся математические операции с локальной переменной 'а' и результат вычисления, находящийся в переменной, с помощью команды Return возвращаем из функции. Этот результат как бы встает на место My(a) ,  то есть переменная 'а' в основном коде будет равна работе функции. Обязательно поиграйтесь с примером.
 В процедуре и в функции можно так же объявлять переменные, структуры или массивы. Они как и параметры тоже будут локальными. Кроме того в функциях и процедурах можно использовать все изученные нами логические команды и циклы.
Однако при всем этом нельзя объявлять функции или процедуры в других функциях или процедурах. Но можно вызывать любые функции или процедуры из функций или из процедур. Примеры:

Так нельзя:

Sub my()
    Sub my_2()
        
    End Sub
End Sub


А вот так можно:

Sub my()
    Print "YES"
End Sub

Sub my_2()
    my()
End Sub

И вот так можно:

Function my()
    Print "YES"
End Function

Sub my_2()
    my()
End Sub

Возвращать значения из функций можно тремя способами:

1) с помощью команды Return:

Function my ( a As Byte ) As Byte
    a=a^2
    Return a
End Function

Print my(5)
Sleep


2) с помощью команды function:

Function my ( a As Byte ) As Byte
    a=a^2
    Function = a
End Function

Print my(5)
Sleep


3) или с помощью имени самой функции:

Function my ( a As Byte ) As Byte
    a=a^2
    my = a
End Function

Print my(5)
Sleep


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

Еще как бы бонусом к этой статье, хочется подметить:

Процедуру можно вызывать без скобок, синтаксис FreeBasic это позволяет. Многие программисты, которые часто имеют дело с ассемблером, попросту привыкли к такой записи (там с помощью макроса Invoke, вызов функции с 4 параметрами выглядит примерно так):

invoke My 10 , 10 , 40 , 22

А в freebasic она выглядит так:

My 10 , 10 , 40 , 22

Хотя можно вызывать и так:

My( 10 , 10 , 40 , 22)

Я предпочитаю последнюю.

Мы рассмотрели вкраце функции и процедуры и это далеко не все про них, но на данном этапе достаточно. Всего доброго!

содержание | назад | вперед