Массивы как формальные параметры процедур

Лабораторная работа № 7

 

Программные единицы

 

1. Цель работы

 

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

 

2.Теоретические сведения

В создаваемом пользователем проекте могут использоваться:

1. встроенные процедуры;

2. подключаемые процедуры;

3. создаваемые при разработке проекта процедуры.

Встроенные процедуры входят в состав Фортрана и автоматически включаются в исполняемый код при обращении к ним в тексте программы (например, процедуры sin, mod, tan и т.д.).

Подключаемые процедуры находятся в ранее созданных библиотеках. Для их использования в программной единице следует подключить к ней модуль, содержащий используемые при работе с процедурами глобальные данные и интерфейсы. Такое подключение выполняется оператором USE. Пользователь может создать собственные прикладные библиотеки и использовать хранимые в них процедуры и модули в любом из своих проектов. Для доступа к содержащим объектный код библиотекам пользователю следует указать ее имя в опции компилятора /link.

Создаваемые при разработке проекта процедуры - это процедуры, которые создаются программистом при решении конкретной задачи.

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

1. Отобразить процесс разбиения в виде блок-схемы и пронумеровать в ней фрагменты

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

3. Для каждого фрагмента разработать алгоритм в виде блок-схемы.

4. Оформить выделенные фрагменты в виде программных единиц.

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

Любая программа имеет одну головную программу, которая находится в начале программы. В общем виде головную программу можно представить:

[PROGRAM имя программы]

[операторы описания]

[исполняемые операторы]

END [PROGRAM [имя программы]]

Оператор PROGRAMзадает имя программы – любое правильно сформированное имя Фортрана. Выполнение программы всегда начинается с первого исполняемого оператора головной программы. Оператор END завершает выполнение программы. Нормальное завершение программы может быть также выполнено оператором STOP, который может быть размещен как в головной программе, так и в процедуре.

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

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

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

Структура процедуры-подпрограммы :

                   SUBROUTINE имя подпрограммы [([список формальных параметров])]

                       [операторы описания]

                       [исполняемые операторы]

                 END[ SUBROUTINE [имя подпрограммы]]

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

Структура процедуры-функции:

                [type] FUNCTION имя функции ([список формальных параметров]) &

                          [RESULT (имя результата)]

                       [операторы описания]

                       [исполняемые операторы]

                 END [FUNCTION [имя функции]]

    Заголовок функции содержит оператор FUNCTION. Функция обязана содержать результирующую переменную, в которую помещается возвращаемый функцией результат. В качестве результирующей переменной может являться либо имя функции, следующее за оператором FUNCTION, либо имя результата, задаваемое в предложении RESULT. Имя результата не должно совпадать с именем функции. Предложение RESULT может отсутствовать. Тип результирующей переменной определяет тип функции и может быть задан посредством указания type в заголовке функции. Type в заголовке может быть опущен, тогда тип результирующей переменной может быть задан явно в одном из операторов объявления функции или неявно. При задании процедуры - функции также следует объявлять ее тип в разделе объявлений вызывающей программной единицы.

Вызов процедуры -подпрограммы выполняется следующим оператором:

        CALL имя подпрограммы ([список фактических параметров])

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

Result = имя функции ([список фактических параметров])

Возврат в вызывающую программную единицу осуществляется при выполнении оператора END в подпрограмме и процедуре – функции. Также он может осуществляться и с помощью оператора RETURN.

Обмен данными между процедурой и вызывающей программной единицей.

    Обмен данными между процедурой и вызывающей программной единицей может быть выполнен через параметры.

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

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

Фактические параметры Формальные параметры
Простая переменная Простая переменная
Строка Строка
Подстрока Строка
Массив, сечение массива или элемент массива Массив или простая переменная
Процедура Процедура
Выражение, константа Переменная

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

 

Пример: Сформировать вектор с1 из элементов вектора а, которых нет в векторе b1. Затем сформировать вектор с2 из элементов вектора а, которых нет в векторе b2. Формирование массивов выполнить в подпрограмме.

 

 

Из головной программы part вызывается внешняя процедура-подпрограмма fobs. При первом вызове в подпрограмму посылаются фактические параметры: массив а и его размер na, массив b1 и его размер nb1; из подпрограммы возвращаются фактические параметры: массив с1 и его размер nc1. При втором вызове посылаются фактические параметры: массив а и его размер na, массив b2 и его размер nb2; из подпрограммы возвращаются фактические параметры: массив с2 и его размер nc2.
program part

integer, parameter:: na=10, nb1=5, nb2=7

integer:: a(na)=(/1,-1,2,-2,3,-3,4,-4,5,-5/)

integer:: b1(nb1)=(/1,-1,2,-2,3/)

integer:: b2(nb2)=(/1,-1,2,-2,3,-3,4/)

integer c1(na), c2(na), nc1, nc2

call fobs(a, na, b1, nb1, c1, nc1)

call fobs(a, na, b2, nb2, c2, nc2)

print *, c1(:nc1)

print *,c2(:nc2)

end program

 
Объявлена внешняя процедура-подпрограмма fobs. Входные формальные параметры – массив а и его размер na, массив b и его размер nb. Выходные формальные параметры – массив с и его размер nc. В данном примере формальные параметры строго соответствуют фактическим параметрам по типу, количеству, порядку следования. Формальным массивам а, b и с ставятся в соответствие фактические массивы а, b1 и с1 (при первом вызове) и фактические массивы а, b2 и с2 (при втором вызове). Формальным переменным na, nb, nc ставятся в соответствие фактические переменные na, nb1, nc1 (при первом вызове) и фактические переменные na, nb2, nc2 (при втором вызове).


subroutine fobs(a, na, b, nb, c, nc)

integer na, nb ,a(na), b(nb)

integer c(na), nc

integer i, j, va

nc=0

loop_a: do i=1,na

va=a(i)

do j=1,nb

if(va==b(j)) cycle loop_a

enddo

nc=nc+1

c(nc)=va

enddo loop_a

end

 

Интерфейсы между процедурами и вызывающими программными единицами.

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

- имя процедуры;

- ее вид (подпрограмма или функция);

- свойства функции (если процедура-функция) (тип, результирующая

переменная);

- имена, положение и свойства формальных параметров.

Возможны два случая задания интерфейса:

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

- интерфейс задается явно. Это делается при помощи интерфейсного блока, имеющего вид

Тело интерфейса содержит описание одного и более интерфейсов процедур. Как правило, интерфейс процедуры – это точная копия заголовка процедуры, объявлений ее формальных параметров, типа функции в случае процедуры-функции и оператора END процедуры Интерфейсный блок должен быть размещен среди операторов описания вызывающей программной единицы
 interface                

...

тело интерфейса

 

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

В теле интерфейса присутствует интерфейс одной процедуры fobs. Этот интерфейсный блок должен быть размещен среди операторов описания головной программы
Interface               

subroutine fobs(a, na, b, nb, c, nc)

integer na, nb, a(na), b(nb)

integer c(na), nc

end subroutine fobs

 end interface

В приведенном примере обязательной необходимости в явном интерфейсе нет.

Однако существуют случаи, когда задание явного интерфейса необходимо.

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

    В процедурах форма и размер массива – формального параметра могут определяться в момент вызова процедуры. Можно выделить 3 вида массивов- формальных параметров: заданной формы, перенимающие форму и перенимающие размер. Рассмотрим первый из них.

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

 Формы фактического и соответствующего ему формального параметра – массива могут отличаться.

Пример: Создать процедуру обмена содержимого двух массивов.

Между вызывающей программой и процедурой swap устанавливается интерфейс во время вызова процедуры по фактическим массивам a, b и фактическим переменным m, n.
integer, parameter:: m=3, n=4, k=m*n

real a(m, n)/k*1/, b(m, n)/k*2/

call swap(a, b, m, n )

write (*,'(3(/10x,4f5.2))') ((a(i, j), i=1,3), j =1,4)

end

а, b – массивы заданной формы, нижняя граница их измерений равна 1, верхняя граница = m*n, где m, n – передаваемые в процедуру значения из вызывающей программы; формальные массивы а, b и фактические массивы а, b имеют разные формы; с – автоматический массив; автоматический массив – это локальный массив в процедуре, размер которого меняется при разных вызовах процедуры
subroutine swap(a, b, m, n)

integer m, n

real a(m*n), b(m*n)

real c(size(a))

c=a

a=b

b=c

end

 

3. Примеры задач и их решение в языке Фортран

 

Пример 1. Дана целочисленная матрица D(mxn). Вывести первый отрицательный элемент каждого столбца матрицы. Использовать процедуру-подпрограмму.

Блок-схема:

 

 

Программа:   

Program pp_1

integer, parameter:: m=4,n=4

integer D(m,n)/10,-4,5,-3,7,8,-20,10,-2,-5,11,13,15,6,-13,-5/,c(m)

Do j=1,n

c=D(:,j)

call poisk(c,m,k)

print *,k

enddo

end

subroutine poisk(c,m,k)

integer c(m),k

Do i=1,m

if(c(i)<0) then

k=c(i)

return

endif

enddo

end

 

Пример 2. Даны три целочисленных массива a(n), b(m), c(k). В каждом из них найти количество четных элементов. Найденные значения поместить в вектор. Использовать процедуру-функцию.

Блок-схема:

Программа:  

Program pp_2

integer, parameter:: m=6,n=8,k=10

integer:: a(m)=(/-6,8,7,3,4,12/)

integer:: b(n)=(/42,-56,77,11,32,55,44,88/)

integer:: c(k)=(/12,-22,33,13,11,8,6,9,19,15/)

integer v(3),col

v(1)=col(a,m)

v(2)=col(b,n)

v(3)=col(c,k)

print *,v

end

integer function col(d,m)

integer d(m),k

k=0

Do i=1,m

if(mod(abs(d(i)),2)==0) k=k+1

enddo

col=k

end

 

 

4. Варианты заданий

 

Вариант
1 Даны две действительные матрицы размера m´n. Определить в каждой матрице суммы элементов столбцов и поместить их в вектора. Использовать процедуру – подпрограмму.
2 Даны три массива а(0:6), в(-3:4), с(10:15). Для каждого массива найти сумму индексов их нулевых элементов. Использовать процедуру – функцию.
3 Даны две матрицы целых чисел. Подсчитать в каждом столбце матриц количество положительных элементов. Использовать процедуру – подпрограмму.
4 Даны две матрицы вещественных чисел. В каждой из этих матриц найти столбец с максимальной суммой элементов. Использовать процедуру – подпрограмму.
5 Ввести массивы вещественных чисел D(10) и K(12), содержащие некоторое число нулевых элементов. Для каждого массива найти номер и значение последнего ненулевого элемента. Использовать процедуру – подпрограмму.
6 Даны два символьных массива 3х4, в которых хранятся имена студентов. В каждом массиве определить количество имен ‘Lena’ и ‘Kirill’. Использовать процедуру – подпрограмму.
7 Даны три массива а(0:6), в(-1:5), с(0:4). Для каждого массива найти логический массив-маску для элементов, которые кратны 3 и не кратны 5. Распечатать его. Посчитать количество таких элементов. Использовать процедуру – подпрограмму.
8 Даны три массива а(-10:-5), в(0:6), с(-1:6). Найти в каждом массиве количество чисел без дробной части. Использовать процедуру – функцию.
9 Даны две матрицы mхn. Найти в каждой из них сумму квадратов элементов и затем определить наибольшую из этих сумм. Использовать процедуру – функцию.
10 Даны два массива а(-1:3), d(6:9). Для каждого массива найти факториалы его элементов. Использовать процедуру – подпрограмму.

 


Дата добавления: 2018-04-05; просмотров: 539; Мы поможем в написании вашей работы!

Поделиться с друзьями:




Мы поможем в написании ваших работ!