Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
272
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

риложение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

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

array = scan ((/'fortran', 'masm

'/), (/'a', 'a'/))

 

 

print *, array

!

6

2

76

риложение3. Организация данных

TRIM(string) - преобразовывающая функция; удаляет завершающие пробелы строки string, например:

print *, 'banana ' // 'nbc'

! banana nbc

print *, trim('banana ') // 'nbc'

! banananbc

VERIFY(string, set [, back]) - элементная функция; возвращает 0, если каждый символ строки string присутствует в строке set. В противном случае возвращает номер позиции символа строки string, которого нет в строке set. Результат имеет стандартный целый тип. Если логический параметр back отсутствует или задан со значением .FALSE., то выдается положение самого левого такого символа. Если back задан со значением .TRUE., то выдается положение самого правого такого символа, например:

write(*, *) verify ('banana', 'nbc')

!

2

write(*, *) verify ('banana', 'nbc', .true.)

!

6

write(*, *) verify ('banana', 'nba')

!

0

Замечания:

1.В Фортран 90 дополнительно включены функции: IACHAR, ACHAR, ADJUSTL, ADJUSTR, REPEAT и TRIM. Все остальные символьные функции были доступны в Фортране 77.

2.Вызов встроенных функций может быть выполнен с ключевыми словами (разд. 8.11.4), например:

print *, verify('banana', set = 'nbc', back = .true.)

!

6

3.Параметрами элементных функций INDEX, SCAN, VERYFY помимо скаляров могут быть массив и скаляр или согласованные массивы. В этом случае результат может быть записан в целочисленный массив, согласованный с массивом-параметром.

4.Параметром элементных функций ADJUSTL и ADJUSTR может также быть и массив. В этом случае результат может быть записан в символьный массив, согласованный с массивом-параметром.

Пример:

character(4), dimension(2) :: st = (/ 'abcd', 'dab'/), ch*1 / 'a', 'b' /

character(7), dimension(2) :: ast = (/ 'abcd

', 'dab

'/), arst

integer(4) p(2)

 

 

 

p = index(st, 'a')

 

 

 

print '(2i4)', p

!

1

2

p = index(st, ch)

 

 

 

print '(2i4)', p

!

1

3

print '(i4)', len(st)

!

4

 

arst = adjustr(ast)

 

 

 

print *, arst

!

abcd dab

 

 

 

 

77