Appearance
Strings and I/O
The type
fortran
use stringifor
type(string) :: sA string has one component, raw, an allocatable character of deferred length and of kind CK (the default character kind). It is allocated by the first assignment and it takes the length of what is assigned:
f90
program allocation_status
!< A string is allocated by its first assignment.
use stringifor
implicit none
type(string) :: s
print '(L1,1X,I0)', s%is_allocated(), s%len()
s = ''
print '(L1,1X,I0)', s%is_allocated(), s%len()
s = 'some text'
print '(L1,1X,I0)', s%is_allocated(), s%len()
call s%free
print '(L1)', s%is_allocated()
endprogram allocation_status$ allocation
F 0
T 0
T 9
Fis_allocated()tells whether the string has been assigned;len()is 0 for a string not allocated.freedeallocates it.- Most methods called on a string not allocated return a string not allocated (or zero, or false).
Assignment, concatenation, comparison
f90
program operators
!< Assignment, concatenation and comparison.
use stringifor
implicit none
type(string) :: a, b, c
character(:), allocatable :: chars
a = 'Hello' ! from a character
b = a ! from a string
c = a//' '//'World' ! // gives a character, assigned to a string
chars = a//' again' ! or kept as a character
c = a .cat. ' World' ! .cat. gives a string
print '(A)', c//''
print '(A)', chars
print '(3(L1,1X))', a == b, a == 'Hello', a /= c
print '(3(L1,1X))', a < c, 'Apple' < a, a >= b
endprogram operators$ operators
Hello World
Hello again
T T T
T T T| Operator | Operands | Result |
|---|---|---|
= | a string from a string, a character, an integer or a real of any kind | — |
// | string and string, string and character, character and string | character |
.cat. | the same | string |
==, /=, <, <=, >=, > | the same | logical, the comparison of the characters |
// returns a character on purpose: it is what makes a string usable wherever Fortran expects a character.
Printing
f90
program print_a_string
!< Three ways to print a string.
use stringifor
implicit none
type(string) :: s
s = 'Hello World'
print '(A)', s//'' ! concatenation gives a character
print '(A)', s%chars() ! the raw characters
print '(DT)', s ! defined I/O
endprogram print_a_string$ print_string
Hello World
Hello World
Hello WorldTIP
The //'' idiom is the shortest way to pass a string where a character is expected, a print or the argument of any procedure. chars() does the same and it is safe on a string not allocated: it returns an empty character.
The DT edit descriptor uses the defined I/O of the type; it requires a compiler that supports defined derived-type I/O (gfortran ≥ 7.1).
WARNING
A string does not go to an A edit descriptor: print '(A)', s is not standard Fortran. The defined output of the type is used only by a DT edit descriptor or by list-directed output (12.6.4.8.4), and any other edit descriptor receives the components of the type, which shall not be allocatable (12.6.3): raw is. The compilers do not diagnose it at compile time: gfortran prints nothing, silently, while ifx stops with a run-time error (severe 125). Pass a character instead, s//'' or s%chars(), or use DT.
Reading
List-directed and formatted reads accept a string. A list-directed read takes one blank-delimited word, or a quoted text:
f90
program read_standard_input
!< Read strings with list-directed input.
use stringifor
implicit none
type(string) :: first, second
read *, first, second
print '(A)', '['//first//'] ['//second//']'
endprogram read_standard_input$ echo '"two words" three' | read_stdin
[two words] [three]To read from files, a line or a whole file at a time, see Files and Paths.
Unformatted I/O stores a string exactly: write(unit) astring writes its length, an I8P integer, then its characters, and read(unit) astring allocates and reads them back, trailing blanks included; a string not allocated is written as a null one. Unformatted files written by versions before 1.4.0, which held the characters only, are not readable.
f90
program binary_io
!< Strings saved to and loaded from an unformatted file.
use stringifor
implicit none
type(string) :: saved(3), loaded(3)
integer :: unit, s
saved(1) = 'Venture'
saved(2) = ' blanks kept '
saved(3) = ''
open(newunit=unit, file='names.bin', form='unformatted', access='stream', status='replace')
write(unit) saved ! each string: its length, then its characters
close(unit)
open(newunit=unit, file='names.bin', form='unformatted', access='stream', status='old')
read(unit) loaded
close(unit, status='delete')
do s = 1, size(loaded)
print '(I2,A)', loaded(s)%len(), ' characters: ['//loaded(s)//']'
enddo
endprogram binary_io$ binary_io
7 characters: [Venture]
15 characters: [ blanks kept ]
0 characters: []The Fortran intrinsics
adjustl, adjustr, count, index, len_trim, repeat, scan, trim and verify are overloaded for strings, as functions and as methods:
f90
program intrinsics_on_strings
!< The Fortran intrinsics, on strings.
use stringifor
implicit none
type(string) :: s
s = ' hello '
print '(A)', '['//trim(s)//']'
print '(A)', '['//adjustl(s)//']'
print '(I0)', len_trim(s)
print '(I0)', index(s, 'll')
print '(A)', repeat(s%strip(), 3)//''
endprogram intrinsics_on_strings$ intrinsics
[ hello]
[hello ]
7
5
hellohellohelloThey behave like the intrinsics: trim removes the trailing blanks only, adjustl keeps the length. To remove the blanks at both ends use strip.
INFO
len is a method (s%len()) but it is not overloaded as a function of the module, to avoid conflicts with the intrinsic in some compilers.
Arrays of strings
Each element of an array has its own length, and the methods are elemental: they apply to a whole array.
f90
program arrays_of_strings
!< A method applied to every element of an array.
use stringifor
implicit none
type(string) :: names(3), glue
integer :: n
names(1) = 'ada' ; names(2) = 'grace hopper' ; names(3) = 'linus' ! elements of different lengths
names = names%startcase() ! the methods are elemental
print '(A)', glue%join(array=names, sep=', ')//''
print '(3(I0,1X))', names%len()
print '(3(L1,1X))', names%start_with('G')
n = maxloc(names%len(), dim=1)
print '(A)', 'the longest is '//names(n)
endprogram arrays_of_strings$ arrays
Ada, Grace Hopper, Linus
3 12 5
F T F
the longest is Grace HopperWARNING
An array of strings must be allocated before it is assigned as a whole: the assignment of the type is a defined one, and it does not allocate its left-hand side. The methods that return several strings (split, justify, glob, read_file) are subroutines that allocate their result.