современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран
Скачать 2.24 Mb.
|
67 О. В. Бартеньев. Современный ФОРТРАН character(len = *), parameter :: ast(3) /'jan', 'febr', 'march'/ print *, len(ast) ! 5 - длина каждого элемента массива Длина элемента символьного массива вычисляется по максимальной длине инициализирующих массив символьных буквальных констант. В нашем примере такой константой является 'march'; 2) звездочка (*) может быть применена для задания длины символьного элемента при объявлении формальных символьных параметров. В этом случае длина формального параметра равна длине фактического параметра. Например: character(len = 15) :: st = 'example', st2*20 /'example_2'/ call sub(st) call sub(st2) end subroutine sub(st3) character(len = *) st3 ! Длина st3 равна длине фактического параметра print *, len(st3) end 3) при объявлении длины возвращаемого внешней нерекурсивной символьной функцией результата также может быть использована звездочка. В таком случае действительная длина результата определяется в операторе CHARACTER той программной единицы, в которой осуществляется вызов функции. Например: integer, parameter :: n = 20 character(len = 4) :: ins = '+ - ' character(len = n) st, stfun ! Длина возвращаемого функцией stfun st = stfun(ins) ! результата равна n print *, st ! # + - + - + - + - # end function stfun(pm) character(len = *) pm ! Длина строки pm равна длине строки ins ! Длина возвращаемого символьной функцией результата определяется ! в той программной единице, где эта функция вызывается character(len = *) stfun character(len = len(stfun)) temp ! Строка temp - пример temp = pm // pm //pm // pm ! автоматического объекта данных stfun = '# ' // trim(temp) // ' #' ! для таких объектов не могут быть end ! заданы атрибуты SAVE и STATIC Символьные операторные или модульные функции, функции-массивы, функции-ссылки и рекурсивные функции не могут иметь спецификацию длины в виде звездочки (*). 68 риложение3. Организация данных 3.8.3. Автоматические строки Процедуры могут содержать не только строки, перенимающие размер от фактического параметра (в последнем примере это строка pm), но и локальные символьные переменные, размер которых определяется при вызове процедуры. В нашем примере это строка temp. Такие переменные относятся к автоматическим объектам данных, которые создаются в момент вызова процедуры и уничтожаются при выходе из нее. Автоматические объекты не должны объявляться с атрибутами SAVE или STATIC. 3.8.4. Выделение подстроки Рассмотрим строку st из 10 символов со значением "Это строка". Подобно элементам массива, символы строки расположены в памяти компьютера один за другим (рис. 3.1). Ячейка памяти Э т о с т р о к а st(1:1) st(2:2) st(10:10) Рис. 3.1. Строка в памяти ЭВМ Каждый символ строки имеет номер. Причем 1-й символ имеет номер 1, 2-й - номер 2 и т. д. Запись st(i:i)обеспечивает доступ к i-му символу строки. Пример. Сколько раз буква 'т' содержится в строке st? character(len = 20) :: st = 'Это строка' integer(2) :: k, j k = 0 do j = 1, len_trim(st) ! Функция LEN_TRIM возвращает if(st(j:j) == 'т') k = k + 1 ! длину строки без завершающих end do ! пробелов print *, ' k =', k ! Напечатает: k = 2 end В Фортране можно выделить из строки любую ее подстроку: st([first]:[last]) first - арифметическое выражение вещественного или целого типа, которое определяет первый символ в подстроке. По умолчанию значение first равно единице, и если first не задан, то подстрока начинается с первого символа строки. last - арифметическое выражение вещественного или целого типа, которое определяет последний символ в подстроке. По умолчанию значение last равно длине строки, и если last не задан, то подстрока оканчивается последним символом строки st. 69 О. В. Бартеньев. Современный ФОРТРАН Замечания: 1. При необходимости дробная часть first (last) отбрасывается. 2. Значения first и last должны быть больше нуля; last не может превышать длину строки; first ≤ last. 3. Записи st(:) и st эквивалентны. 4. Операция выделения подстроки может быть также применена к элементу символьного массива и к символьному элементу записи. Например: character st*20 /'It''s a string'/ ! st - строка; arrst - массив строк character(len = 15) arrst(10) /'It''s a string ', 9*'One more string'/ write(*, *) st(1 : 6) ! или st(:6) It's a write(*, *) arrst(2)(10 : 15) ! или arrst(2)(10:) string 3.8.5. Символьные выражения. Операция конкатенации Фортран содержит единственную символьную операцию - операцию конкатенации (//). Результатом операции является объединение строк - операндов символьного выражения. Длина результирующей строки равна сумме длин строк-операндов. Операндами символьного выражения могут быть: • символьные константы и переменные; • символьные массивы и их сечения; • элементы символьных массивов; • вызовы символьных функций; • символьные подстроки; • символьные компоненты производных типов. Пример: character(len = 12) st1, st2 ! Строки длиной в 12 символов character(len = 24) st data st1, st2 /'first', 'second'/ print *, st1 // ' & ' // st2 ! first & second st = st1( : len_trim(st1)) // ' & ' // st2( : len_trim(st2)) print *, st ! first & second st = trim(st1) // ' & ' // trim(st2) print *, st ! first & second Замечания: 1. Чтобы не потерять часть символов при объединении строк, надо следить, чтобы длина строки, которой присваивается результат конкатенации, была не меньше суммы длин объединяемых строк. 2. Функция LEN_TRIM вычисляет длину строки без завершающих пробелов. 3. Функция TRIM возвращает строку без завершающих пробелов. 70 риложение3. Организация данных 4. Для выделения строки без завершающих пробелов применяется функция TRIM, например: st = trim(sb) В более ранних версиях то же самое выполнялось так: st = sb(:len_trim(sb)) 3.8.6. Присваивание символьных данных Оператором присваивания в переменную символьного типа устанавливается результат символьного выражения: символьная переменная = символьное выражение Символьная переменная - строка, подстрока, символьный массив, символьные элементы записей. Длина символьной переменной может отличаться от длины строки - результата символьного выражения: character st*9 /'Строка 1'/, stnew*14 /'Новая строка'/, st2 /'2'/ st = stnew ! 'Новая стро' st = st2 ! '2 ' st2 = stnew // st ! 'Н' Если символьной переменной является подстрока, то в результате присваивания изменяются принадлежащие подстроке символы: character st*20 /'Строка 1'/, stnew*14 /'Новая строка'/, st2 /'2'/ st(8:) = stnew(1:5) ! 'Строка Новая' st(14:14) = st2 ! 'Строка Новая 2' Присваивание символьных массивов и их сечений возможно, если они согласованы (разд. 4.6), например: character(1) st(4) /'a', 'b', 'c', 'd'/, st2(4) character(len=3) res(4) ! Символьный массив из четырех элементов; st2 = st ! длина каждого элемента массива равна трем res = st // st2 ! Все массивы согласованы write(*, *) res ! aa bb cc dd 3.8.7. Символьные переменные как внутренние файлы В Фортране символьная строка, подстрока и символьный массив являются внутренними файлами, т. е. файлами, существующими в оперативной памяти ЭВМ. В случае строки или подстроки этот файл имеет лишь одну запись, длина которой совпадает с длиной символьной переменной. В случае символьного массива число записей в файле равно числу его элементов. Для передачи данных при работе со строками как с внутренними файлами используются операторы В/В: READ(u, fms) список ввода WRITE(u, fms) список вывода 71 О. В. Бартеньев. Современный ФОРТРАН u - устройство В/В (см. разд. 10.2 и 10.3). При ссылке на внутренний файл номером устройства является имя символьной переменной, например строки, подстроки или символьного массива. fms - спецификатор формата В/В, который в случае В/В под управлением неименованного списка задается в виде звездочки (*). Используя оператор WRITE, в строку можно передать данные любых типов. И наоборот, оператором READ из строки можно считать, например, числовые данные (если в строке есть числовые поля данных). Часто при помощи оператора WRITE числовые данные преобразовываются в символьные, например число 123 в строку '123', а также формируются строки, состоящие из смеси числовых и символьных данных. Например, для обеспечения вывода сообщений, содержащих числовые данные, в графическом режиме посредством подпрограммы OUTGTEXT или при работе с диалоговыми окнами. Пример. Преобразовать заданные числа (a и b) в символьное представление. Выполнить также обратное преобразование "строка - число". integer(2) :: a = 123, a2 real(8) :: b = -4.56 character(10) sta, stb, ste, st*50 write(sta, '(A, I3)') ' a = ', a write(stb, '(F8.3)') b ! Номер устройства В/В совпадает с именем write(ste, '(E10.4)') b ! строки, в которую выполняется запись данных print *, sta, stb, ste ! a = 123 -4.560 -.4560E+01 write(st, '(A, I3, F7.2, E12.5)') ' a & b & b: ', a, b, b print *, st ! a & b & b: 123 -4.56 -.45600E+01 read(st,'(12X,BZ,I3)') a2 ! Читаем из st значение a2 print *, a2 ! 230 write(st, *) ' a : ', a ! Вывод под управлением списка print *, st ! a : 123 Пояснение. При чтении из строки (внутреннего файла) использованы преобразования: 12X - перемещение на 12 символов вправо, I3 - перевод последовательности символов '23 ' в число 230. Пробел интерпретируется как 0 благодаря дескриптору BZ. 3.8.8. Встроенные функции обработки символьных данных Фортран содержит встроенные функции, позволяющие оперировать символьными данными. Встроенные функции разделяются на элементные, справочные и преобразовывающие. Аргументами элементных функций могут быть как скаляры, так и массивы. В последнем случае функция возвращает согласованный с массивами-параметрами массив. Значение элемента возвращаемого массива определяется в результате применения функции к соответствующему элементу массива-аргумента. Ряд функций, 72 риложение3. Организация данных например ICHAR или INDEX, возвращают значение стандартного целого типа INTEGER, имеющего по умолчанию параметр разновидности KIND = 4. Однако если применена опция компилятора /4I2 или директива $INTEGER:2, то тип INTEGER будет эквивалентен типу INTEGER(2) и, следовательно, функции стандартного целого типа, например INDEX, также будут возвращать значения типа INTEGER(2). IACHAR(c) - элементная функция; возвращает значение стандартного целого типа, равноеASCII-коду символа c. Тип параметра c - CHARACTER(1). Пояснение. Каждому символу поставлено в соответствие целое положительное число, называемое кодом символа. Американский стандарт обмена данными ASCII кодирует 128 символов, включающих управляющие символы, символы цифр, строчные и прописные буквы английского алфавита, знаки препинания и ряд других широко используемых символов. ASCII-коды символов расположены в диапазоне от 0 до 127. Первый ASCII- символ (символ с кодом 0) является пустым (null) символом - ''. Таким символом заканчивается любая СИ-строка. Коды со значениями, большими 127, употребляются для кодировки национальных алфавитов. Особенности кодировки русского алфавита рассмотрены в прил. 1. ICHAR(c) - элементная функция; возвращает значение стандартного целого типа, равноекоду символа c из поддерживаемой операционной системы таблицы символов. Тип параметра c - CHARACTER(1). Пояснение. На практике операционная система может поддерживать отличную от ASCII кодировку символов. Получить доступ к системной таблице символов позволяет функция ICHAR. Правда, в Windows NT и Windows 95 последовательность символов с кодами от 0 до 127 совпадает с ASCII-последовательностью. Поэтому только для символов с кодами больше 127 IACHAR и ICHAR могут возвращать разные значения. Пример. Вывести прописные буквы русского алфавита, коды которых в системной и ASCII-таблицах не совпадают. character(1) caps(32) /'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З', & 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', & 'ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я'/ integer :: n = 0 ! Число различий do i = 1, 32 ! Сравнение кодов if(iachar(caps(i)) /= ichar(caps(i))) then print *, ' ', i, caps(i) n = n + 1 end if end do if(n == 0) print *, 'Нет различий' end 73 О. В. Бартеньев. Современный ФОРТРАН ACHAR(i) - элементная функция; возвращает символ типа CHARACTER(1), код которого в таблице ASCII-кодов символов равен i (0 ≤ i ≤ 255). Тип i - INTEGER. CHAR(i [, kind]) - элементная функция; так же, как и функция ACHAR, возвращает символ типа CHARACTER(1), код которого в таблице ASCII- кодов символов равен i (0 ≤ i ≤255). Тип i - INTEGER. В отличие от ACHAR функция CHAR позволяет задать значение параметра разновидности символьного типа. Правда, в настоящее время символьный тип существует только с параметром разновидности KIND = 1. Значение параметра разновидности результата совпадает с kind, если параметр задан, и равно единице в противном случае. Пример. Вывести на экран множество символов 8-битового кода, выводя на строчке по 15 символов. Напомним, что на 8 битах можно задать код для 256 символов с кодовыми номерами от 0 до 255. do i = 1, 255, 15 ! Вывод всех, кроме null, символов write(*, *) (' ', char(j), j = i, i + 14) end do Замечание. Функции IACHAR, ICHAR, ACHAR, CHAR являются элементными, т. е. их аргументом может быть массив, например: integer(4) iabc(5) character(1) :: ABC(5) = (/ 'A', 'B', 'C', 'D', 'E' /) iabc = ichar(ABC) print *, iabc ! 65 66 67 68 69 iabc = ichar((/'a', 'b', 'c', 'd', 'e'/)) print *, iabc ! 97 98 99 100 101 end LGE(string_a, string_b) - элементная функция; возвращает .TRUE., если строка string_a больше строки string_b или равна ей, иначе результат функции - .FALSE. LGT(string_a, string_b) - элементная функция; возвращает .TRUE., если строка string_a больше строки string_b, иначе результат функции - .FALSE. LLE(string_a, string_b) - элементная функция; возвращает .TRUE., если строка string_a меньше строки string_b или равна ей, иначе результат функции - .FALSE. LLT(string_a, string_b) - элементная функция; возвращает .TRUE., если строка string_a меньше строки string_b, иначе результат функции - .FALSE. Замечания: 1. Если сравниваемые параметры имеют разную длину, то при сравнении их длина выравнивается за счет дополнения более короткого параметра пробелами справа. 74 риложение3. Организация данных 2. Сравнение выполняется посимвольно слева направо. Фактически сравниваются коды (ASCII) символов. 3. Параметрами функций LGE, LGT, LLE, LLT могут быть согласованные массивы. В этом случае результат может быть присвоен логическому массиву, согласованному с массивами-параметрами. Пример. Вывести из списка фамилии, начинающиеся с буквы 'Н' или с последующих букв алфавита. character(len = 20) group(30) /'Алферов', 'Салтыков', & 'Новиков', 'Влазнев', 'Николаев', 25*'?'/ integer(2) i do i = 1, 30 if(lge(group(i), 'Н')) then write(*, *) group(i) ! Салтыков end if ! Новиков end do ! Николаев end Для полноты изложения отметим, что тот же результат будет получен и в случае применения обычной операции отношения ' ≥ ' - .GE. или >=: if(group(i) >= 'Н') write(*, *) group(i) LEN(string) - справочная функция; возвращает длину строки string. Результат имеет стандартный целый тип. Задание значения строки string необязательно. Параметр string может быть символьным массивом. В этом случае функция возвращает длину элемента массива. Пример: character sta(20)*15, stb*20 write(*, *) len(sta), len(stb) ! 15 20 LEN_TRIM(string) - элементная функция; возвращает длину строки string без завершающих пробелов. Результат имеет стандартный целый тип. Параметр string может быть символьным массивом. Пример: character(len = 20) :: stb = 'One more string' character(len = 20) st, st2 /' '/ write(*, *) ' Len_trim_stb=', len_trim(stb) ! Len_trim_stb = 15 write(*, *) len_trim( st ), len_trim( st2 ) ! 20 0 write(*, *) len_trim('It''s a string ') ! 13 ADJUSTL(string) - элементная функция; выполняет левое выравнивание символьной строки: удаляет все ведущие пробелы и вставляет их в конец строки, например: print *, adjustl(' banana') // 'nbc' ! banana nbc 75 О. В. Бартеньев. Современный ФОРТРАН ADJUSTR(string) - элементная функция; выравнивает символьную строку по правой границе за счет удаления всех завершающих пробелов и их последующей вставки в начало строки, например: print *, 'banana ' // 'nbc' ! banana nbc print *, adjustr('banana ') // 'nbc' ! banananbc INDEX(string, substring [, back]) - элементная функция; возвращает номер позиции, с которой начинается первое вхождение строки substring в строке string. Результат имеет стандартный целый тип. Если параметр back отсутствует или задан со значением .FALSE., то поиск ведется слева направо. Если значение back есть .TRUE., то поиск ведется справа налево, т. е. начиная с конца строки. Если строка substring не содержится в строке string, то функция возвратит 0. Номер позиции в любом случае исчисляется от начала строки. Пример: character(120) sta /'Снег, снег, снег, снег, снег над тайгою... '/ print *, index(sta, 'снег') ! 7 print *, index(sta, 'снег', .true.) ! 25 REPEAT(string, ncopies) - преобразовывающая функция; возвращает строку, содержащую ncopies повторений строки string (выполняет ncopies конкатенаций строки string), например: character(10) st st = repeat('Na', 5) !NaNaNaNaNa SCAN(string, set [, back]) - элементная функция; возвращает номер позиции первого найденного в строке string символа строки set. Если логический параметр back отсутствует или задан со значением .FALSE., то выдается положение самого левого такого символа. Если back задан со значением .TRUE., то выдается положение самого правого такого символа. Функция возвращает 0, если в строке string нет ни одного символа строки set. Результат имеет стандартный целый тип. Пример: integer array(2) print *, scan('Fortran', 'tr') ! 3 print *, scan('Fortran', 'tr', back = .true.) ! 5 print *, scan('FORTRAN', 'ora') ! 0 array = scan((/'fortran', 'visualc'/), (/'a', 'a'/)) print *, array ! 6 5 |