Skip to content

Strings and I/O ​

The type ​

fortran
use stringifor
type(string) :: s

A 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
F
  • is_allocated() tells whether the string has been assigned; len() is 0 for a string not allocated.
  • free deallocates 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
OperatorOperandsResult
=a string from a string, a character, an integer or a real of any kind—
//string and string, string and character, character and stringcharacter
.cat.the samestring
==, /=, <, <=, >=, >the samelogical, 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 World

TIP

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
hellohellohello

They 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 Hopper

WARNING

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.