Farionova_Fortran
.pdfТема5. РаботасфайламивФортране
По умолчанию используются 'OLD' – для ввода и 'NEW' – для вывода.
Атрибут ERR используется для указания метки оператора, который будетвыполнятьсявслучайвозникновенияошибкиприоткрытиифайла.
Атрибут ACTION определяет действие, для которого открывается файл:
ACTION = 'READ' – только для чтения;
ACTION = 'WRITE' – только для записи;
ACTION = 'READWRITE' – для чтения и для записи.
Длянепосредственночтенияилизаписивфайлиспользуютсяфункции write и read, как для любого другого устройства:
READ (12,*) a,b,c
После выполнения необходимых действий с файлом его нужно закрыть и отсоединить от устройства оператором close. В данном слу-
чае close(12).
Рассмотрим примеры программной реализации организации работы с внешними текстовыми файлами:
Open (Unit=10,File='1.Dat')
Open (Unit=11,File='1.Dat',Status='New',Iostat=Ios)
If( Ios/=0) Then
Write(6,*) 'Error Opening File: 1.Dat.'
Stop
Endif
Пример. Файл "data.txt" содержит следующие данные:
3 |
3 |
3 |
1 |
2 |
|
4 |
5 |
6 |
7 |
8 |
9 |
В первой строке находится количество строк и столбцов матрицы соответственно, в последующих сама матрица.
Фрагмент программы, который позволяет считать данные из файла в переменные k , l, a(dimension):
52
5.2. Организация работы с файлами
Open(5,file='data.txt') Read(5,*), k,l
Do i=1,k Read(5,*),(a(I,1:l)) Enddo
Close(5)
Пример. В двухмерном массиве А находятся данные
1 |
2 |
-3 |
7 |
4 |
-5 |
6 |
-9 |
-7 |
8 |
9 |
0 |
Ниже приведен фрагмент программы, который позволяет записать эти данные в файл "res.dat" в таком порядке: первая строка – количество строк, вторая – количество столбцов матрицы, дальше построчно строкиматрицы:
Open(6,file='res.dat', status="new") write(6,*), k
write(6,*), l Do i=1,k
write(6,*),(a(I,1:l)) Enddo
Close(6)
В результате в файле "res.dat" будут записаны следующие данные:
3 |
|
|
|
4 |
2 |
-3 |
7 |
1 |
|||
4 -5 |
6 |
-9 |
|
-7 |
8 |
9 |
0 |
53
Тема 6. Программные единицы.
Подпрограммыифункции
6.1. Общие понятия
При создании программ появляется необходимость выполнять некоторую последовательность команд (инструкций) в различных местах программы. Эту последовательность можно записать необходимое количество раз, но, во-первых, это удлинит текст программы и снизит ее читабельность (последнее, несомненно, хуже для программиста) и, вовторых, существенноувеличитвероятностьвнесенияошибоквпрограмму.
При разработке алгоритма исходная задача, как правило, разбивается на отдельные подзадачи. Квалификация программиста во многом определяется его способностью рационально разбить исходную задачу на фрагменты, которые впоследствии реализуются в виде отдельных программныхединиц.
ВФортране можно создать такие программные единицы:
•главная программа;
•модули;
•внешниепроцедуры;
•внутренниепроцедуры;
•BLOCK DATA.
Вэтой теме будут рассмотрены особенности использования внешнихивнутреннихпроцедур.
Внешняя процедура является самостоятельной программной единицейисуществуетнезависимоотиспользующихеепрограммныхединиц.
Клюбой внешней процедуре можно обратиться из главной программы илюбойдругойпроцедуры.
Внешниепроцедурымогуткомпилироватьсяотдельноотиспользующихихпрограммныхединиц.
Внутренняя процедура задается в главной программе, процедуре. Главная программа и процедура называются носителями содержащихсявнихвнутреннихпроцедур. Обратитьсяквнутреннейпроцедуре можно только внутри ее носителя. Сами же внутренние процедуры уже
не могут содержать в себе другие внутренние процедуры.
54
6.1. Общиепонятия
Преимуществоиспользованияпрограммныхединиц:
•позволяют сократить расходы на создание программы;
•улучшают читаемость программы и, следовательно, облегчают
еепоследующуюмодификацию;
•приводят к сокращению исходного кода;
•могутбытьвключенывбиблиотекиивызваныизлюбойпрограммы;
•позволяют разделить работу над программой между разными программистами.
Процедура – это фрагмент кода, который вынесен из основной программы и имеет уникальное имя. Тогда в месте, где необходимо выполнить эту последовательность кода, нужно просто сослаться на ее имя.
Это называется вызовом программной компоненты.
Например, необходимо несколько раз напечатать несколько одинаковых строчек:
*,'--------------------------- |
' |
|
*,'*********************' |
' |
|
*,'--------------------------- |
Вместо того чтобы несколько раз в теле программы набирать (или копировать, что несколько лучше) эти три строки, можно оформить их в виде подпрограммы:
subroutine PrtSomething! |
имя подпрограммы |
|
*,'--------------------------- |
' |
|
*,'*********************' |
||
*,'--------------------------- |
' |
|
end |
|
|
Теперь в любом месте программы, где должна производиться соответствующая печать, нужно вызвать эту подпрограмму по ее имени:
call PrtSomething
Когда использовать процедуры? Есть мнение, что если в какой-то программе больше 10 строк кода, то ее надо разбить на процедуры. Общие правила написания структурированных, хорошо читаемых программ: еслинекоторыйучастоккодаимееткакое-тообособленноесмыс- ловое значение – выделяйте его в виде процедуры. Это дает несколько преимуществ: удобствочтения, уменьшениевероятностивнесенияошибок.
55
Тема6. Программныеединицы. Подпрограммыифункции
6.2. Программная компонента функция
Процедуру следует оформлять в виде функции, если ее результат можнозаписатьводнупеременную, т. е. восновнуюпрограммупередается только одно значение, как в последнем случае.
Структурафункцииимеетследующийвид:
FUNCTION < имя функции>( [< форм.арг >])
<объявление форм.арг >
<объявление локальных объектов >
...
<вычисляемые операторы, присваивание результата >
END [ FUNCTION [ < имя функции > ] ]
Пример:
function Sum_(a,b) real a,b,Sum_
Sum_=a+b return
end
…
s=Sum_(1.,3.)
Функциибываютвнешниеивнутренние. Призаданиивнешнейфункции следует объявлять ее тип в разделе объявлений вызывающей программной единицы, как это делается для других объектов данных.
Внутренниепроцедурыобладаютявнозаданныминтерфейсом, поэтому тип внутренней функции не должен объявляться в ее носителе. Внутренниепроцедуры-функциинемогутсодержатьдругиевнутренние процедуры.
Вызов функции осуществляется путем указания ее имени в вызывающей ее программной компоненте.
Пусть требуется вычислить выражение |
s = |
f (x + ∆x) |
+ f (x) , где |
||||||
f (x − ∆x) |
|||||||||
|
|
|
|
|
|
|
|
||
f (x) = |
sin(x) + cos(x) |
, |
x = |
π |
, ∆x = 0,01. |
|
|
|
|
x + e x |
8 |
|
|
|
|||||
|
|
|
|
|
|
|
56
6.2. Программнаякомпонентафункция
Без применения собственных функций программа будет иметь вид
Program bezfunc
Real, parameter :: pi=3.1415926 Real x, dx, s, fp, fm, f0 X=pi/8
Dx=0.01
F0=(sin(x)+cos(x))/(x+exp(x)) ! вычисление f(x) Fp=(sin(x+dx)+cos(x+dx))/(x+dx+exp(x+dx)) ! вы-
числение f(x+dx) Fm=(sin(x-dx)+cos(x-dx))/(x-dx+exp(x-dx)) ! вы-
числение f(x-dx) S=fp/fm+f0
Write(*,'(a, f5.2)'), 's=', s end
Результат работы программы:
S = 1.68
С использованием инструмента функций в Фортране вычисление
f (x) = sin(x) + cos(x) можно описать как собственную внутреннюю x + e x
функцию с одним формальным аргументом x после слова contains. А в программе просто использовать ее вызовы.
Program s_func
Real, parameter :: pi=3.1415926 Real x, dx, s
X=pi/8
Dx=0.01
S=f(x+dx)/f(x-dx)+f(x) ! вызов функции Write(*,'(a, f5.2)'), 's=', s
Contains
Function f(x) ! начало функции Real x
F=(sin(x)+cos(x))/(x+exp(x)) ! вычисление выра- !жения, результат присваивается имени функции
End function f ! конец функции end
Результат работы программы:
S = 1.68
57
Тема6. Программныеединицы. Подпрограммыифункции
6.3. Процедураподпрограмма
Кромефункций, существуетвторойвидпроцедур– подпрограммы. Ониявляютсяболееуниверсальнымипрограммнымикомпонентами, так как могут не только возвращать в основную программу значения вычислений, ноиосуществлятьопределенныедействия(например, выпол- нятьспециальныеоперацииввода–вывода, обрабатыватьмассивыипр.). Подпрограммы бывают внутренние и внешние.
Структура подпрограммы имеет следующий вид:
SUBROUTINE < имя подпрограммы>( [< форм.арг >])
<объявление форм.арг >
<объявление локальных объектов >
<вычисляемые операторы, присваивание результата > END [ SUBROUTINE [ < имя подпрограммы > ] ]
Как и функция, подпрограмма записывается отдельно от основной программы, после оператора Contains. Подпрограммы, описанные внутри программы после оператора Contains, называются внутрен-
ними подпрограммами.
Вызовподпрограммыпроисходитприпомощиоператораcall, после которого следует имя подпрограммы и фактические параметры. При использовании подпрограмм формальные и фактические параметры могут отсутствовать.
Рассмотрим пример программы, выводящей рамку с сообщениями:
program frame character(12) s
s=' ATTENTION '; call message(s) write(*,*)
s='STOP'; call message(s) Contains
subroutine message(text) character(12) text write(*,*)'********************' write(*,*)'* ',s,' *' write(*,*)'********************' end subroutine message
end
58
6.4. Формальные и фактические параметры подпрограмм и функций
Результат работы программы:
********************
*ATTENTION *
********************
********************
*STOP *
********************
6.4.Формальные и фактические параметры подпрограммифункций
Обмен данными между процедурой и вызывающей программной единицей может быть выполнен через параметры процедуры. Параметры, используемые при вызове процедуры, называются фактическими. Параметры, используемые в процедуре, называются формальными.
Привызовепроцедурымеждуфактическимииформальнымипараметрами устанавливается соответствие (формальные параметры ассоциируются с соответствующими фактическими).
Для того чтобы сделать доступными какие-то данные процедуры, их надо передать в списке параметров, который стоит сразу за именем подпрограммы в скобках:
subroutine PrеValues(a,b,c).
Параметры, записанные в заголовке подпрограммы, называются формальными параметрами (аргументами). Для подпрограммы это просто переменные. Параметры, подставленные в месте вызова подпрограммы, называются фактическими параметрами. В качестве фактических параметров могут быть константы, переменные или результаты выражений.
subroutine PrеValues(a,b,c)! имя подпрограммы
! описание переменных – формальных параметров integer a,b
real c
!тело подпрограммы print *,'a= ',a print *,'b= ',b print *,'c= ',c
end
59
Тема6. Программныеединицы. Подпрограммыифункции
В подпрограмму PrеValues(a,b,c) передаются значения трех переменных, которые и печатаются. Формальные параметры – переменные, существующиеТОЛЬКОвподпрограмме. ОниВИДНЫТОЛЬКО в подпрограмме. Если вне подпрограммы есть переменные с такими же именами, они не имеют ничего общего!
Вызов этой подпрограммы может выглядеть так:
integer a1/4/,a2/7/ real pi/3.14159
call PrеValues(1,2,7.)! 1 2 7 call PrеValues(1,2.,7.)! ERROR!
Припервомвызовеподпрограммывпеременную а будетположено значение 1, в b – 2, в c – 7. Соответственно подпрограмма распечатает их в таком виде:
a=1
b=2
c=7
Почемунеправильныйпоследнийпример? Интерфейсподпрограммы предписывает, что подпрограмма ДОЛЖНА вызываться с тремя фактическими параметрами, имеющими соответствующий тип, совпадающий с типом формальных подпрограмм. Отсюда вытекает следующееправило:
Список формальных и фактических параметров должен совпадать по количеству и характеристикам аргументов.
Другимисловами, сколькопараметровописановзаголовкеподпрограммы, столько же должно стоять в операторе вызова (за некоторыми исключениями), тип и длина каждого фактического параметра должны совпадатьстипомидлинойсоответствующегопопорядкуформального
(рис. 6.1).
Параметры могут служить для передачи значений не только внутрь подпрограммы, но и в обратном направлении. При этом значение переменной – формального параметра кладется в соответствующее окошко, а вызывающая сторона забирает его и кладет в переменную – фактический параметр.
60
6.4. Формальные и фактические параметры подпрограмм и функций
subroutine Sum(a,b,c) real a,b,c
c=a+b return end
…
call Sum(1.,3.,s)
В переменную s поместится результат сложения фактических параметров– констант1 и3. Важнообратитьвнимание: еслиформальный параметр в подпрограмме является [in] – входящим (вводящим значениевподпрограмму), товкачествефактическогопараметраможетбыть переменнаяиликонстанта(первые2 параметраSum); еслижеформальный параметр в подпрограмме является [out] или [in/out] – выходящим (возвращающим значение из подпрограммы), то в качестве фактического параметра может быть только переменная (3 параметра Sum).
logical d character c integer b
real a
...
call proc (a, b, c, d)
...
contains
subroutine proc (x, k, s, p) real x
integer k character s
logical p
...
end
Рис. 6.1. Соответствиемеждуформальными и фактическими параметрами
61