Chapter 12 — Key Takeaways (Strings and Text)

A one-page reference for modern Fortran text handling: self-sizing strings, the character intrinsics, and internal files.

The two (and a half) kinds of string

Declaration Kind Length is… Use it for
character(len=n) :: s fixed-length constant; value blank-padded a field of known width; a scratch buffer
character(:), allocatable :: s deferred-length set by assignment; re-sizes the default — strings that fit their contents
character(len=*), intent(in) :: s assumed-length dummy taken from the caller every string procedure argument

Reach for character(:), allocatable. It is the allocatable idea (Ch. 5, Ch. 11) applied to characters: owns its memory, freed automatically, s = value reallocates to fit, len(s) is always exact.

The character intrinsics (what each returns)

Call Returns Note
len(s) declared/allocated length includes trailing blanks
len_trim(s) length without trailing blanks 0 if all blank
trim(s) s minus trailing blanks trim(adjustl(s)) strips both ends
adjustl(s) left-justified; leading blanks → tail length preserved
adjustr(s) right-justified; trailing blanks → front length preserved
index(s, sub[, back]) 1-based position of sub, else 0 back=.true. → last occurrence
scan(s, set[, back]) first char in set, else 0 find a delimiter / a digit
verify(s, set[, back]) first char not in set, else 0 == 0 ⇒ all chars are in set

Idioms worth memorizing

  • Strip both ends: trim(adjustl(s))
  • Present? index(s, sub) > 0 · Absent? index(s, sub) == 0
  • All digits? verify(tok, '0123456789') == 0
  • Start of content (skip leading blanks): verify(s, ' ')
  • File extension: index(name, '.', back=.true.)

Concatenation and substrings

whole = 'heat' // '_' // 'map'   ! // joins; length is the sum
part  = s(3:7)                    ! substring: 1-based, inclusive, length j-i+1
  • Always trim a fixed-length variable before // or its trailing blanks splice in: trim(dir) // '/' // file, never dir // '/' // file.
  • A substring s(i:j) is a string like any other; if i > j it is zero-length.

Internal files (number ↔ text)

write(str, fmt) values     ! number -> text (like sprintf / f-string)
read (str, fmt) variables  ! text -> number (like sscanf / int(),float())
  • The "unit" is a character variable; no open, no disk. Same edit descriptors as Chapter 7.
  • write(fname, '(a,i6.6,a)') 'heat_', step, '.vtk'heat_000123.vtk.
  • read(line, *) a, b, c splits '3 14 159' on blanks → 3, 14, 159.

Edit descriptors you use here

Descriptor Effect Example
i0 integer, minimum width (never overflows) 255255
iw.m width w, ≥ m digits, zero-padded i6.6 of 123000123
fw.d real, width w, d decimals f8.3 of 3.141593.142
a character, exact 'heat'heat

Common pitfalls

  • Trailing-blank splice: dir // '/x' with fixed-length dir buries blanks. → trim(dir).
  • index is not a boolean: if (index(s,sub)) doesn't compile; write > 0 / == 0.
  • Field overflow → *: i4.4 of 12345 prints ****. Size the field, or use i0.
  • 1-based, 0-when-absent: porting Python find (0-based, −1 absent) needs two corrections.
  • Off-by-one in tokenizers: offsets from scan/verify on line(pos:) are relative — add pos-1.

The tokenizer, in one breath

verify finds where a token starts (first non-delimiter); scan finds where it ends (next delimiter). Skip-then-take in a loop; a run of delimiters is skipped in one verify, so extra spaces never make empty tokens. scan/verify take a set, so ' ,' tokenizes comma-or-space data unchanged.

Modern vs legacy (the point of the chapter)

FORTRAN 77 Modern
Only string kind fixed-length deferred-length available
True length tracked by hand in an integer carried by the string (len(s))
Build a value write into s(a:b), update n s = s // piece

Modern Fortran is a modern language: deferred-length strings delete the manual length counter — an entire class of bookkeeping and bugs — that FORTRAN 77 forced on you.

Project piece added this chapter

frame_name(step) — a function returning a deferred-length filename heat_NNNNNN.vtk built with an internal-file write write(buf, '(a,i6.6,a)') 'heat_', step, '.vtk'. The six zero-padded digits make frames sort in time order; Chapter 26 calls it to name per-timestep VTK output. Ceiling: i6.6 holds 999,999 steps — widen to i8.8 beyond that.

Key terms

deferred-length character · fixed-length character · assumed-length (len=*) · internal file · substring · concatenation (//) · trim/adjustl (the character-intrinsic family) · index/scan/verify · tokenizer.