Название: Информатика. Алгоритмический язык Фортран - учебное пособие (Худяков Д.С., Саблина Г.В.)

Жанр: Информатика

Просмотров: 3092


2.9. ввод и вывод на фортране

 

Операторы ввода и вывода, как уже отмечалось, по своей структуре близки (отличаются только ключевым словом) и имеют следующий вид:

READ(n,m) <список переменных>

WRITE(n,m)<список переменных>

Здесь первый оператор ввода, а второй оператор вывода; n – номер канала ввода или вывода; m – метка оператора FORMAT, который определяет порядок расположения данных в строке при вводе или выводе; <список переменных> – вводимые или выводимые переменные.

Ранее была описана простейшая система бесформатного ввода с клавиатуры и вывода на экран. Для этого в операторах READ или WRITE вместо номера устройства ввода-вывода и метки оператора FORMAT располагаются символы «*» (звездочка).

Опишем процедуру организации ввода-вывода с использованием файлов. В этом случае файл, с которого будет осуществляться ввод-вывод, нужно связать с номером канала ввода-вывода. Для этого используется оператор открытия файла вида

OPEN(n,FILE ='<имя файла>')

где n – номер канала, которым может быть любое целое число,

n £ 32767, а имя файла подчиняется описанным выше правилам.

Примеры:

OPEN(10,FILE='DANN.DAT')

READ(10,*)X,Y,M

 

OPEN(15,FILE='REZULT.DAT')

WRITE(15,*) (B(I), I=1, N)

В первом примере открывается канал ввода с номером 10, которым является файл DANN.DAT. Поскольку в операторе READ вместо метки оператора FORMAT указан символ *, то осуществляется бесформатный ввод. Это означает, что в файле DANN.DAT в той же последовательности, что и в списке переменных, должны быть записаны значения X, Y, M, между которыми должно быть не менее одного пробела, например:

-7.35 0.5Е-11 89

Во втором примере открывается канал вывода с номером 15, которым является файл REZULT.DAT. Поскольку вывод также бесформатный, то элементы массива В будут записаны в файл через пробел в той же последовательности, что и в списке переменных.

Файл может быть отсоединен от канала ввода-вывода с помощью оператора закрытия файла, который имеет вид:

CLOSE(n)

где n – номер канала. Одновременно с закрытием канала файл может быть удален, если использовать оператор

CLOSE(n,STATUS='DELETE')

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

В Фортран-программе может быть любое количество каналов ввода-вывода, которые могут открываться операторами OPEN в любой части программы. Файлы, связанные с каналами ввода-вывода, должны находиться в том же каталоге, где помещен запускаемый файл Фортран-программы с расширением .ехе. Если файла с соответствующим именем в каталоге нет, то оператор OPEN создает пустой файл с этим именем. Ясно, что такой возможностью можно пользоваться только для каналов вывода. Если файл, предназначенный для канала вывода, не пустой, то перед записью выводимых данных его содержимое будет уничтожено. Исключение составляет случай, когда тот же канал был ранее использован для вывода исходных данных.

Иногда бывает удобно не связывать номер канала ввода-вывода

с именем конкретного файла, т.е. номер канала n присутствует в операторе READ или WRITE, но он не открыт оператором OPEN. Тогда

в процессе выполнения программы на экране появляется сообщение

file name missing or blank-please enter file name

UNIT n?

После этого вопроса на клавиатуре нужно набрать имя файла, которое вы хотите связать с номером n канала ввода-вывода.

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

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

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

m FORMAT(S)

где m – обязательная метка оператора, a S – список спецификаций формата, разделенных запятыми.

Для каждого типа данных существует своя спецификация: для целых величин – спецификация I, для вещественных величин – F или Е, для вещественных величин двойной точности – спецификация D, для логических величин – спецификация L. Для комплексных величин используются две спецификации вещественных величин.

Общая форма спецификации I

Iw

где w – беззнаковая целая константа, показывающая количество символов (длину поля), отводимых для ввода или вывода целых величин. Например, в спецификации I5 целые величины –5712 и 359 будут представлены

-5712 и 359

а в спецификации I4 первая величина не может быть представлена, а вторая будет иметь вид:

_359

Поэтому при задании спецификации I необходимо учитывать примерный порядок вводимых или выводимых величин.

Если число меньше длины поля w, то при вводе и выводе левая часть поля заполняется пробелами.

Если при вводе число занимает больше w символов, то считываются только w левых символов. Например, запись

–1352764

по спецификации I5 будет считана как

-1352

Если при выводе число занимает больше w символов, то в отводимом для записи числа поле будут напечатаны звездочки «*».

Заметим, что с помощью спецификации I11 можно ввести или вывести любую целую величину, поскольку диапазон изменения целых чисел от  –2147483648  до  2147483647.

Общая форма спецификации F

Fw.d

где w – общая длина поля, включая знак числа и десятичную точку,

a d – число цифр после десятичной точки.

Спецификация F предназначена для вещественных чисел без показателя степени. Во всех случаях w > d для положительных чисел и

w > d + 1 для отрицательных. Например, в спецификации F7.3 числа

–72,591 и 24,52 будут представлены как

-72.591 и _24.52_.

Если при выводе целая часть числа занимает больше w – (d + 1) сим-волов, то в отводимом для записи числа поле будут напечатаны звездочки «*».

Вещественные числа с порядком представляются с помощью спецификации Е, общий вид которой

Ew.d

где w – общая длина поля, a d – число цифр после десятичной точки в мантиссе.

Величины w и d связаны соотношением w > d + 6, которое обусловлено необходимостью записи в поле знака числа, десятичной точки мантиссы, символа Е, порядка числа и его знака. Например, в спецификации Е11.4 числа  и  будут представлены как

-0.2567Е-11 _2.3000Е__2.

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

Спецификация вещественных величин двойной точности имеет вид:

Dw.d

где w – общая длина поля, a d – число цифр после десятичной точки в мантиссе. Эта спецификация аналогична спецификации Е и к ней применимы те же правила с учетом того, что символ D определяет показатель степени. Например, числа

 и

в спецификации D16.9 будут представлены в виде

-2.356789012D-24 _1.134500000D__2.

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

Lw

где w – длина поля.

При вводе логических величин поле просматривается слева направо и если первым встречается символ Т или F, то переменной присваивается значение .TRUE. или .FALSE. соответственно. Если же эти символы не присутствуют в поле, то переменной присваивается значение .FALSE.

При выводе символы Т или F располагаются в крайней правой позиции поля, а остальная часть поля заполняется пробелами.

Например, в спецификации L2 логические значения .TRUE. и .FALSE. будут представлены при выводе как

Т _F

Отметим, что спецификации должны соответствовать типу вводимых или выводимых данных.

Чтобы отделить вводимые или выводимые данные w пробелами, между спецификациями данных указывается

wX

Например, спецификация пробелов 3Х обеспечит пропуск трех позиций при вводе или выводе.

Для записи текста между выводимыми данными используется спецификация, имеющая вид

'Т'

где Т – текст, состоящий из любых символов Фортрана и русских букв.

Опишем характер взаимодействия вводимых или выводимых данных из списка переменных в операторах READ или WRITE со спецификациями оператора FORMAT. Пусть

Р1, ..., Рk

– список переменных в операторе ввода или вывода, а

S1, ..., Sk

– список спецификаций в соответствующем операторе FORMAT, который связан с одной записью (строкой). Количество символов в строке однозначно определяется списком спецификаций и, как правило, не должно превосходить 80.

Каждой спецификации в порядке слева направо отводится соответствующее поле в строке. При этом спецификации пробелов при вводе-выводе и спецификации текста при выводе присутствуют в соответствующих местах строки без каких-либо изменений.

Числовые и логические спецификации из списка S1, …, Sk в порядке слева направо ставятся в соответствие переменным Р1, ..., Рk, которые согласно этим спецификациям представляются в строке. Если список переменных меньше, чем количество числовых и логических спецификаций, то последующие спецификации игнорируются. Если список переменных больше, чем количество числовых и логических спецификаций, то ввод-вывод осуществляется на первой строке до конца списка спецификации, а последующие переменные вводятся или выводятся с новой строки вместе с переходом в начало списка спецификации и т.д. до конца списка переменных.

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

m FORMAT(...,S,...,S,...)

                                                   N раз

эквивалентна записи

m FORMAT(...,NS,...)

а запись

m FORMAT(...,S1,...,Sn,...,S1,...,Sn,...)

                                                                    N раз

эквивалентна записи

m FORMAT(...,N(S1,...Sn),...)

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

OPEN(1 ,FILE='DAT.TXT')

READ(1,5)A,X,M

 5 FORMAT(2F5.2,I3)

необходимо в файл DAT.TXT записать с помощью любого текстового редактора значения переменных А, Х, М, из которых первые две – переменные вещественного типа, а третья – переменная целого типа. Пусть А = 1,45, В = –0,56, М = 45. Тогда в первой строке файла начиная с крайней левой позиции нужно записать

_1.45-0.56_45

При выводе согласно операторам

    OPEN(5,FILE='REZ.DAT')

    WRITE(5,5)GX,K,P

     5 FORMAT(2X,'GX=',F4.1,1X,'K=',I4,1X,'P=',F5.2)

для переменных со значениями GX = –7,4, K = 29, Р = –359,6 будем иметь в строке файла REZ.DAT

_GX=-7.4_K=__29_P=*****

В данном случае переменная Р не могла быть размещена в поле спецификации F5.2, и вместо нее были напечатаны символы «*».

Пусть в результате выполнения программы для аргументов Х1 = 1,5 и  Х2  =  3,0   были   найдены   соответствующие    значения   функции

F1 = 0,5632945×10–2, F2 = –0,1429123×10–14. Тогда результаты можно вывести с помощью следующих операторов вывода:

OPEN(15,FILE='REZULT.DAT')

WRITE(15,10)X1,F1,X2,F2

      10 FORMAT(2X,'X=',F3.1,1X,'F=',E10.3)

При этом в файле REZULT.DAT будут следующие две строки:

__X=1.5_F=_0.563E_-2

 X=3.0_F=-0.143E-14

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

WRITE(*,*)'A=',A,'B=',B

WRIТЕ(*,*)'ЗАДАТЬ ЗНАЧЕНИЕ М'

READ(*,*)M

В первом примере на экране появится текст «А=», затем числовое значение А, потом текст «В=» и числовое значение В. Во втором примере на экране появится текст:

ЗАДАТЬ ЗНАЧЕНИЕ М

после чего на клавиатуре нужно набрать число, соответствующее М. Рассмотрим пример ввода одномерного целочисленного массива А с количеством элементов не более 100

INTEGER А(100)

WRITE(*,*)'K='

READ(*,*)K

OPEN(3,FILE='DAN.DAT')

READ(3,5)(A(I),I=1,K)

      5  FORMAT(4(I2,1X))

Пусть значение K = 9, а элементы массива следующие: А(1) = 10, А(2) = 24, A(3) = 5, A(4) = 7, A(5) = 2, A(6) = 29, A(7) = 0, A(8) = 44, А(9) = 15. Тогда после появления на экране текста «K=» необходимо набрать на клавиатуре число 9, а затем из файла DAN.DAT, который должен состоять из строки

10_24__5__7__2_29__0_44_15

будут считаны элементы массива.

Рассмотрим пример ввода комплексных величин. Пусть С1 =

= 2,5 – i3,97, С2 = –0,345 + i4,5. Тогда при использовании операторов ввода

COMPLEX C1,C2

OPEN(1,FILE='DAN.DAT')

READ(1,2)C1,C2

2 FORMAT(4F6.3)

необходимо, чтобы файл DAN.DAT имел вид:

_2.500-3.97_-0.345_4.5__

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

COMPLEX C1,C2

OPEN(1,FILE='DAN.DAT')

READ(1,*)C1,C2

файл DAN.DAT будет иметь вид:

2.5,-3.97_-0.345,4.5

При форматном выводе на экран или принтер первый символ в скобках оператора FORMAT не печатается, а интерпретируется как символ управления кареткой. Действия, выполняемые при записи символов пробел, 0, +, указаны в табл. 2.1. Любой другой символ воспринимается как символ пробела.

 

                                                                                           Т а б л и ц а  2.1

 

Символ

Действие

пробел

Переход на следующую строку

0

Переход через две строки

+

Передвижения не происходит

 

Следующие операторы FORMAT соответствуют перечисленным управляющим символам

m FORMAT(1X,S)

m FORMAT('0',S)

m FORMAT('+',S)

где S – список спецификаций.

2.10. Подпрограммы

 

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

<тип> FUNCTION <имя> (S)

операторы Фортрана

RETURN

END

Здесь <тип> – определяет тип результата (INTEGER, REAL и т.д.) подпрограммы, <имя> – имя подпрограммы, подчиняющееся обычным правилам образования имен в Фортране, S – список формальных параметров подпрограммы. Список формальных параметров состоит из имен переменных и массивов, разделенных запятыми.

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

Результатом выполнения подпрограммы-функции является значение, присваиваемое переменной с именем подпрограммы. Если имя подпрограммы соответствует типу результата по умолчанию (REAL или INTEGER), то указание типа в заголовке подпрограммы может быть опущено.

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

ции F вида:

.

Соответствующая программа с использованием подпрограммы-функции может иметь вид:

READ(*,*)X,Y

F=RQ(X,Y)+5/(RQ(X,Y))

WRITE(*,*)'F=',F

STOP

END

 

FUNCTION RQ(A,B)

RQ=A**2+B**2

RETURN

END

В головной программе происходит обращение к подпрограмме RQ, а между фактическими параметрами X, Y и формальными параметрами А, В имеет место соответствие

,

.

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

Рассмотрим пример вычисления суммы четных положительных элементов одномерного массива с количеством элементов N £ 200. Соответствующая программа может иметь вид:

INTEGER A(200),SUM

READ(*,*) N,(A(I),I=1 ,N)

IS=SUM(A,N)

WRITE(*,*)'SUM=',IS

STOP

END

 

INTEGER FUNCTION SUM(B,M)

INTEGER B(M)

SUM=0

DO 5 I=1,M

IF(B(I).LE.O)GO TO 5

IF(B(I)/2*2.EQ.B(I))SUM=SUM+B(I)

5 CONTINUE

RETURN

END

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

В Фортране широко используется подпрограмма-процедура, имеющая следующий общий вид:

SUBROUTINE <имя> (S)

операторы Фортрана

RETURN

END

Здесь S – список формальных параметров. Для вызова подпрограммы-процедуры используется специальный оператор CALL, имеющий вид:

CALL <имя> (С)

где С – список фактических параметров. Между формальными и фактическими параметрами должно соблюдаться соответствие по количеству, порядку следования и типу. Оператор CALL помещается в вызывающем программном модуле.

Подпрограмма-функция может иметь большое количество аргументов, но она всегда имеет один явный результат. Поэтому ее формальные параметры имеют смысл «исходных данных», при обработке которых получается определенный результат, присваиваемый переменной с именем подпрограммы. Подпрограмма-процедура может использоваться и в тех случаях, когда необходимо получение нескольких результатов. Поэтому имя подпрограммы SUBROUTINE никак не связано с именем и типом получаемых результатов, а среди формальных параметров находятся как «исходные данные», так и «требуемые результаты».

Рассмотрим пример: сформировать массив С, являющийся суммой двух одномерных массивов А и В с количеством элементов в каждом N < 100. Соответствующая программа с использованием подпрограммы SUBROUTINE имеет вид:

DIMENSION A(100),B(100),C(100)

READ(*,*)N,(A(I),B(I),I=1,N)

CALL SUM(A,B,C,N)

WRITE(*,*)(C(I),I=1 ,N)

STOP

END

 

SUBROUTINE SUM(A,B,Z,N)

DIMENSION A(N),B(N),Z(N)

DO 5 I=1,N

Z(I)=A(I)+B(I)

          5 CONTINUE

RETURN

END

В этом примере осуществляется следующее соответствие фактических и формальных параметров:

,

,

,

.

В п. 2.8 отмечалось, что элементы одномерных массивов хранятся в памяти последовательно один за другим, а элементы многомерных массивов располагаются согласно правилу: быстрее всего изменяется первый индекс, затем второй и т.д. Так, например, элемент двумерного массива с индексами I, J будет занимать ячейку памяти с номером

I + (J – 1)×N, считая от элемента массива с индексом равном единице

(N – предельное значение индекса I в массиве). Поэтому ясно, что если предельные значения индексов многомерного массива в подпро-грамме не совпадают с их значениями в вызывающем программном модуле, то элементы массива с одинаковыми индексами в этих программных модулях не совпадают. Таким образом, если многомерный массив используется в разных программных модулях, то необходимо задавать одинаковые предельные значения их индексов в операторах описания размерности массива.

Рассмотрим задачу умножения двух квадратных матриц А и В размерности N´N для значений N £ 50. Соответствующая программа может иметь вид:

DIMENSION A(50,50),B(50,50),C(50,50)

READ(*,*)N,((A(I,J),B(I,J),I=1,N),J=1,N)

NP=50

CALL MULTI(A,B,C,NP,N)

WRITE(*,*XC(I),I=1,N)

STOP

END

SUBROUTINE MULTI(A,B,C,NP,N)

DIMENSION A(NP,NP),B(NP,NP),C(NP,NP)

DO 5 I=1, N

DO 5 J=1,N

S=0

DO 10 K=1,N

S=S+A(I,K)*B(K,J)

      10 CONTINUE

C(I,J)=S

       5 CONTINUE

RETURN

END

Здесь А и В – заданные матрицы (двумерные массивы), а С – искомая матрица. В головной программе параметр NP должен быть равен предельному значению индексов массивов, указанному в операторе описания размерности. Мы рекомендуем читателю провести эксперимент с заданием других значений NP и посмотреть, какие в этом случае получатся значения элементов массива С.

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