О бедном Фортране
О бедном Фортране[1]...
Э. М. Пройдаков
На вопрос: "На каком языке написана эта программа?"
write (*,*) ‘Hello, World!’
end
не каждый сразу ответит, что на Фортране-77. Для многих из тех, кто видел Фортран-IV ЕС и СМ ЭВМ, Фортран-77 в реализации для ПЭВМ покажется белым лебедем, в которого превратился когда-то популярный гадкий утенок. Этот стереотип настолько силен, что, говоря о выборе языка программирования для той или иной задачи, программисты называют Си/С++, Паскаль, Модулу-2, Бейсик, реже Smalltalk и Форт и как-то морщатся при упоминании о Фортране, считая его архаичным и примитивным. Автор и сам разделял эту точку зрения, пока случайно не познакомился с Мiсrоsoft FORTRAN версии 5.0 для IВМ РС/ХТ/АТ и РS/2 [1-2] (далее MS-Фортран).
Его отличия от Фортрана-IV можно разделить на три группы:
- новые типы данных;
- новые конструкции языка;
- улучшение ввода-вывода.
Новые типы данных
Первое, что порадовало, это возможность записывать константы в любой системе счисления от двоичной до 36-ричной, например:
J=2#11111001 ! двоичная константа
или (то же самое):
J=16#FC !16-ричная константа
Если основание системы счисления больше 10, то новые цифры представляются буквами от А до Z (текст от восклицательного знака до конца строки является комментарием).
Другой интересный объект – это строки, которые могут быть длиной от 1 до 32767 знаков. Строки задаются одним из следующих операторов:
Character *LL имя ! Здесь LL – длина строки,
Character имя *LL ! имя – список имён переменных
Character * (*) имя ! и/или массивов
Character имя * (*) ! Например:
Character имя (const*LL) ! Character*8 My_string, Msg
и ограничиваются как одинарными, так и двойными кавычками. Строки могут сформироваться по правилам языка Си, т. е. заканчиваться нулем, а внутри себя содержать непечатаемые символы, которые задаются с помощью обратной косой черты, например, известное всем \n – новая строка. Чтобы отличить строки, совместимые с Си, от обычных, в конце них ставят латинскую букву С:
'/n Текст сообщения 'C
Так как в М8-Фортране нет пустой строки, то использование '' недопустимо, а ''С – допустимо (это строка длиной 1, содержащая нуль). Подстрока задается как элемент массива указанием её первого и последнего индексов. Если
new_name = ‘123456789’
то
new_name (4:8) ! это подстрока ‘45678’
Если один из индексов опущен, то предполагается индекс первого или последнего элемента соответственно. Так, выполнение
F_Name= ‘kingwi’
Write (*,*) F_Name(4:), F_Name(:2)
выведет на экран слово wiking. Для операции конкатенации строк используется знак //, а не привычный всем +.
Из современных конструкций для представления сложных типов данных в язык введены структуры, массивы структур и объединения:
Structure /str_name/
character*25 city
integer*4 post_index
…
End Structure
Подобным образом вводится структурный тип данных. Переменная или массив этого типа объявляется в операторе
record /str_name/ city_list(100), city_var
Обращение к элементу структуры осуществляется, как обычно, путем указания полного имени, например:
city_list(42).post_index=123060
И, наконец, структуры могут быть вложенными.
Более сложным образом в язык введены объединения – UNION. Для этого создана конструкция, именуемая МАР, которая объявляет компилятору, что перечисленные в ней данные (переменные, массивы и структуры) располагаются в памяти последовательно, в том порядке, как они указаны:
MAP
integer*2 jk,jl,jq
character*12 what
END MAP
Конструкции МАР используются далее в UNION, чтобы задать совмещение по памяти данных более удобно, чем это делается с помощью оператора EQUIVALENCE:
UNION
MAP
integer*4 loopcnt, newstep
END MAP
MAP
character*10 descr
END MAP
…
END UNION
Здесь переменная descr располагается в памяти с того же адреса, что и loopcnt.
Индексы массивов теперь могут задаваться, как в Си.
Наиболее неожиданной возможностью в М8-Фортране является динамическое распределение памяти под массивы, отсутствие которого било бичом Фортрана-IV. Для динамических массивов при их объявлении указывается атрибут ALLOCTABLE и используются операторы аllосаtе и dealloсаtе соответственно для распределения памяти под массив и её освобождения. Например:
integer*2 SoundW [ALLOCTABLE, HUGE] (:,:,:) integer speed,N,M,Error
….
ввод значений speed, N, M и проверка их допустимости
….
allocate (SoundW(speed,N,M), STST=Error)
if Error .NE. 0 then Stop ‘Не хватает памяти…’
… ! вычисления
end
subroutine subprim(speed,N,M,iS)
integer iS[HUGE] (1)
…
end
При этом массив может занимать более 64 Кбайт ОЗУ (атрибут HUGE). Если он не указан, а динамически распределяется память более 64 Кбайт, то это вызывает зависание программы.
Динамические массивы позволяют:
- не использовать в целях экономии памяти один и тот же массив в разных целях, что плохо во всех отношениях;
- не задавать жестко размерность решаемой задачи;
- значительно уменьшить размер ЕХЕ-файла (на объем статических массивов).
Заметим, что в отличие от Си и Паскаля в Фортране-77 нет необходимости возиться с указателями.
Раньше во многих реализациях Фортрана-IV, если у имени массива не указывался индекс, то подразумевался первый элемент массива. В МS-Фортране подразумевается действие, выполняемое над всеми элементами массива, которое называется выражением над массивом (к сожалению, вышесказанное не относится к динамическим массивам). Все встроенные функции, имеющие скалярные аргументы, могут иметь и аргумент в виде массива.
Выражения над массивами позволяют:
- сэкономить около 30 байт кода на каждом цикле;
- ускорить примерно на шесть машинных команд работу с каждым элементом массива.
Примеры.
ZeroArr=0 ! Присваивание константы каждому элементу массива
Arr2=-Arr1 ! Присваивание элемента с обратным знаком
Arr3= Sin(Arr2) ! Применение функции к каждому элементу массива
Arr4=Arr3-Arr1(22) ! Вычитание элемента Arr1(22) из каждого элемента массива Arr3
LogArr = .NOT. LogArr2 ! Работа с массивами типа logical
Новые конструкции языка
В Фортране-77 (и соответственно в МS-Фортране) новые конструкции обеспечивают возможность писать без меток и операторов GOTO. Прежде всего это касается циклов:
Цикл DO
do exp1, exp2 [,exp3]
…. тело цикла…
end do
Цикл DO WHILE
do while exp1
…. тело цикла…
end do
Хотя из тела цикла можно выходить с помощью GОТО, существуют два оператора, позволяющие сделать это более структурно:
- оператор CYCLE передает управление на последний оператор цикла (т. е. осуществляет переход к следующему шагу цикла);
- оператор EXIT передает управление на первый оператор после конца цикла (т.е. выходит из цикла).
Введена Си-подобная конструкция выбора из альтернатив, очевидная из примера:
character*1 cmd
select case (cmd)
case (‘r’,’R’)
call readfrom
case (‘1’:‘8’)
call findkey(cmd)
case (‘A’:’J’, ‘a’:’j’)
write (*,*) ‘Not a Command’
case default
call monitor (cmd)
end select
Конструкция IF также стала более привычной:
if expr1 then
…. ! операторы
end if
либо, в более сложной форме:
if
else if
…
else
end if
Файлы прямого и последовательного доступа по структуре делятся на форматные, неформатные и двоичные.
FORM = ‘BINARY
‘FORMATTED’
‘UNFORMATTED’
Так как часто возникает проблема стыковки различных программ, то данные всегда могут быть в виде ASCII-файла (FORMATTED), но при больших размерах массивов это неудобно. UNFORMATTED-файлы содержат, к сожалению, дополнительную фортрановскую информацию, которую приходится удалять при передаче программе, например на Турбо-Паскале. BINARY-файлы хранят машинное представление данных и поэтому наиболее компактны.
Отметим, что графические возможности МS-Фортрана и МS-Си совпадают, а программы на МS-Фортране выполняются в среднем на 20% быстрее, чем аналогичные на Турбо-Си 2.0.
Заключение
Летом 1991 г. фирма Microsoft выпустила MS-Fortran 5.1, для которого была разработана интегрированная оболочка, облегчена компоновка с библиотекой графических подпрограмм и сделано многое другое.
Возникает законный вопрос: так можно ли писать программы на таком Фортране? Конечно, можно! Только осторожно. Ведь все его "ошибки молодости" (отсутствие строгой типизации имен, разделителей между лексемами и т. д.) остались в нём для совместимости с предыдущими версиями. Требование совместимости, вообще говоря, гарантирует консерватизм языка программирования, т. е. является женским началом. С другой стороны, поглощение языком всё новых конструкций должно быть весьма и весьма обоснованным, и здесь следует избегать всеядности Бейсика. Так велика ли, в конце концов, разница между современными Паскалем, Си, Фортраном и другими процедурными языками? С более общих позиций автор называет этот процесс сближения стремлением процедурных языков к их концептуальному идеалу.
Примечания
1. “О бедном Фортране замолвите слово” – строка из старинного программистского романса. – Прим. автора.
Литература
- Microsoft FORTRAN Reference. Version 5.0 for MS OS/2 and MS-DOS Operating Systems. – USA: Microsoft Corp. 1989. – 524 pp.
- Велецки Я. Фортран–77: Пер. с польск. – М.: Высшая школа, 1991. 207 с.
Статья опубликована в сборнике БИТ, вып. 4. – М.: ИнфоАрт, 1992 г.