- •3.9. Ввод-вывод
- •Виды ввода-вывода данных
- •Управляемый списком ввод-вывод
- •Форматный ввод-вывод
- •3.10. Подпрограммы и функции
- •Структуры процедур
- •Вызов процедуры Вызов процедуры-подпрограммы осуществляется отдельным оператором следующего вида:
- •Упражнения
- •3.11. Массивы
- •Объявление динамических массивов
Вызов процедуры Вызов процедуры-подпрограммы осуществляется отдельным оператором следующего вида:
CALL имя подпрограммы ([список фактических параметров])
Обращение к функции является операндом в выражении. Оно может присутствовать в правой части оператора присваивания. Например:
a = имя функции ([список фактических параметров])
Фактическими параметрами могут быть выражения, буквальные и именованные константы, простые переменные, массивы и их сечения, элементы массивов, записи, элементы записей, строки, подстроки, процедуры и встроенные функции. Если фактический параметр является внешней процедурой, то он должен в описании иметь атрибут EXTERNAL. Если же фактический параметр является встроенной процедурой, то он должен быть объявлен с атрибутом INTRINSIC.
Между формальными параметрами процедуры в описании и фактическими параметрами при обращении к ней должны выполняться правила соответствия:
- соответствие по количеству (сколько формальных параметров, столько же фактических);
- соответствие по последовательности: первый фактический параметр соответствует первому формальному, второй – второму и т.д.
- соответствие по типу: типы соответствующих параметров должны совпадать.
Пример 1. Программа вычисления длин сторон треугольника, заданного координатами вершин, с использованием внутренней функции.
Program Treug1
real x1,y1,x2,y2,x3,y3,r
print*,"Введите: x1,y1,x2,y2,x3,y3"
read*,x1,y1,x2,y2,x3,y3 !(1,1)(2,2)(2,1)
r=S(x1,y1,x2,y2); print*,r !1.414214
r=S(x1,y1,x3,y3); print*,r !1.000000
r=S(x2,y2,x3,y3); print*,r !1.000000
contains
real function S(w1,z1,w2,z2)
real w1,z1,w2,z2
S=sqrt((w1-w2)**2+(z1-z2)**2)
end function S
end program flocal
Пример 2. Программа вычисления длин сторон треугольника, заданного координатами вершин, с использованием внешней подпрограммы.
Program Treug2
real x1,y1,x2,y2,x3,y3,r
print*,"Введите: x1,y1,x2,y2,x3,y3"
read*,x1,y1,x2,y2,x3,y3 !(1,1)(2,2)(2,1)
CALL S(x1,y1,x2,y2,r); print*,r !1.414214
CALL S(x1,y1,x3,y3,r); print*,r !1.000000
CALL S(x2,y2,x3,y3,r); print*,r !1.000000
end program Treug2
subroutine S(w1,z1,w2,z2, L)
real w1,z1,w2,z2, L
L=sqrt((w1-w2)**2+(z1-z2)**2)
end subroutine S
Рекурсивные процедуры
В математике рекурсивным называется определение любого понятия через самого себя. Классическим примером является определение факториала целого числа, большего или равного нулю.
Здесь функция факториал определена через факториал. Нетрудно понять справедливость такого определения. Для n > 0
Вариант 0! = 1 является тривиальным. Но это опорное значение, от которого начинается «раскручивание» всех последующих значений факториала:
1! = 1 * 0! =1*1 =1; 2! = 2 * 1 = 2; 3! = 3 * 2! = 6 и т.д.
Рассмотрим процедуру-функцию, использующую в своем описании приведенную выше рекурсивную формулу.
Recursive function ifact(n) result (fav)
Integer fav, n
If(n=0) then
Fav=1
Else
Fav=n*ifact(n-1)
Endif
End
Тип результата рекурсивной функции может быть задан и следующими двумя способами:
recursive integer function ifact(n) result (fav)
integer recursive function ifact(n) result (fav)
В рекурсивно определенной функции обязательно должна использоваться переменная для результата. В данном примере это переменная fav.
Основная программа, которая использует внешнюю функцию ifact для вычисления величины K!, имеет следующий вид:
Program factorial
Integer K, ifact
Print*, ‘Введите К’
Read*, K
Write(*,’(2X,I2,A,I6)’) K,’!=’, ifact(K)
end
Пусть в основной программе в целую переменную К вводится число 3. При вычислении функции ifact с аргументом 3 произойдет повторное обращение к функции ifact(2). Это обращение потребует вычисления ifact(1). И наконец, при вычислении ifact(0) будет получен числовой результат 1. Затем цепочка вычислений раскрутится в обратном порядке:
ifact (1) = 1 * ifact (0) = 1 ,
ifact(2) = 2*ifact(1) = 2 ,
ifact(3) = 3*ifact(2) = 6.
Последовательность рекурсивных обращений к функции должна обязательно выходить на определенное значение. А весь маршрут последовательных вхождений машина запоминает в специальной области памяти, называемой стеком. Таким образом, выполнение рекурсивной функции происходит в два этапа: прямой ход –– заполнение стека; обратный ход –– цепочка вычислений по обратному маршруту, сохраненному в стеке.
Использование рекурсивных функций — красивый прием с точки зрения программистской эстетики. Однако этот путь не всегда самый рациональный. Рассмотренную задачу с n! можно решить так:
F= 1
do I= 1, N
F= F*I
enddo
Очевидно, что такой вариант программы будет работать быстрее, чем рекурсивный. И в том случае, когда важно сокращение времени выполнения программы, следует отдать предпочтение последнему варианту.