Fortran strings
last modified November 14, 2026
A string is a sequence of characters treated as one value. In Fortran its type
is character, and the unusual part is that every character
variable has a length fixed when the variable is declared. A shorter
value is stored with blanks (spaces) added at the end, and those blanks remain
part of the value. This article shows how to declare strings, join and cut
them, remove padding, compare and search them, work with character codes, and
use the deferred-length form whose size follows the text assigned to it.
Declaring character variables
The length is written in the declaration as character(len=10).
The value assigned may be shorter than the length; the remaining characters
are spaces. Nothing here is a pointer or a reference to the literal: the
variable holds its own copy of the characters, padded to its declared length.
The intrinsic function len reports that declared length, so it
cannot be used to find out how much text a variable really contains.
program s1
implicit none
character(len=10) :: name
character(len=5) :: greeting
name = 'Fortran'
greeting = 'Hello'
print *, 'name: [', name, ']'
print *, 'greeting: [', greeting, ']'
print *, 'len(name): ', len(name)
print *, 'len(greeting):', len(greeting)
end program s1
name receives the seven letters of Fortran and three
blanks, while Hello fills its five characters exactly. The
brackets make the padding visible. The program prints the strings with
print *, the list-directed form of output, where the
compiler chooses the layout; gfortran starts each record with a space, prints
character values one after another without a separator, and gives each integer
a field of its own width. That is why the brackets touch the text and why the
two lengths appear far to the right.
$ gfortran s1.f90 -o s1 $ ./s1 name: [Fortran ] greeting: [Hello] len(name): 10 len(greeting): 5
Concatenation and substrings
The operator // joins two character values and produces a value
whose length is the sum of their lengths. Since a fixed-length variable
carries its padding, joining a padded variable also joins its trailing blanks;
trim removes them first. A substring is a part of a
string chosen with a colon, as in title(1:7). Either index may be
left out: title(9:) means from position 9 to the end, and
title(:3) means the first three characters.
program s2
implicit none
character(len=20) :: title
character(len=10) :: first, second
first = 'Fortran'
second = '2018'
title = trim(first) // ' ' // trim(second)
print *, '[', title, ']'
print *, '[', title(1:7), ']'
print *, '[', title(9:), ']'
print *, 'len_trim:', len_trim(title)
first = 'Ada'
title = first // ' Lovelace'
print *, '[', title, ']'
end program s2
The right-hand side of the first assignment is seven letters, a space and four
digits, twelve characters in all, so the twenty-character variable is padded
with eight blanks. The second and third lines cut the word and the year out of
it, and the year keeps the blanks that follow it, because the substring runs
to the declared end of the variable. len_trim ignores those
blanks and reports 12. In the last part the point is the opposite: assigning
Ada to a ten-character variable stores three letters and seven
blanks, so the concatenation produces those seven blanks in the middle of the
title. Trimming before joining avoids that.
$ gfortran s2.f90 -o s2 $ ./s2 [Fortran 2018 ] [Fortran] [2018 ] len_trim: 12 [Ada Lovelace ]
Trimming and adjusting
Four intrinsics deal with padding. len_trim returns the number of
characters before the trailing blanks, trim returns a copy with
those blanks removed, adjustl moves leading blanks to the end, and
adjustr moves trailing blanks to the front. trim
produces a value shorter than the argument, while the two adjust functions
return a value of the same length with the blanks in a different place; none of
them changes the variable itself.
program s3
implicit none
character(len=12) :: a, b
a = ' Fortran '
b = 'Fortran'
print *, '[', a, ']'
print *, '[', trim(a), ']'
print *, '[', adjustl(a), ']'
print *, '[', adjustr(a), ']'
print *, '[', trim(adjustl(a)), ']'
print *, 'equal after trim:', trim(adjustl(a)) == b
print *, 'equal raw: ', a == b
end program s3
The literal ' Fortran ' has eleven characters, so the twelfth
is a blank, and adjustr moves all three trailing blanks to the
front. Combining trim with adjustl leaves just the
word, which then compares equal to b. The last line shows why the
cleaning matters: compared as stored, the padded a and the padded
b differ, because the blanks sit in different places.
$ gfortran s3.f90 -o s3 $ ./s3 [ Fortran ] [ Fortran] [Fortran ] [ Fortran] [Fortran] equal after trim: T equal raw: F
Comparing strings
Relational operators compare strings character by character using the
character code of each position. If the operands have different lengths, the
shorter one is treated as if it were padded with blanks, so
'abc' and 'abc ' are equal. The codes follow
ASCII: uppercase letters come before lowercase ones, and a prefix is smaller
than the longer word that starts with it.
program s5
implicit none
character(len=5) :: upper, lower
upper = 'Apple'
lower = 'apple'
print *, upper == lower, upper < lower, upper > lower
print *, 'abc' == 'abc ', 'a' < 'B'
print *, 'tab' < 'table'
end program s5
The first line reports that the two words are different, that the capitalised
one sorts first, and that the lowercase one is therefore greater. The second
line shows blank padding making two literals of different lengths equal, and
the capital B coming before the lowercase a. The
last comparison is true because tab is a prefix of
table, and a prefix sorts before the longer string.
$ gfortran s5.f90 -o s5 $ ./s5 F T F T F T
Searching with index, scan and verify
index(s, sub) returns the position of the first occurrence of
sub inside s, or zero when it is absent; adding
back=.true. searches from the end. scan(s, set)
returns the position of the first character of s that appears
anywhere in the string set, and verify(s, set) the
first character that does not appear in it. All three return
positions in the original string, counted from one.
program s4
implicit none
character(len=40) :: s
character(len=5), parameter :: vowels = 'aeiou'
s = 'Fortran is a compiled language'
print *, 'index of "is": ', index(s, 'is')
print *, 'index of "a": ', index(s, 'a')
print *, 'last "a": ', index(s, 'a', back=.true.)
print *, 'first vowel: ', scan(s, vowels)
print *, 'last vowel: ', scan(s, vowels, back=.true.)
print *, 'first other: ', verify(s, 'abcdefghijklmnopqrstuvwxyz ')
end program s4
The word is starts at position 9, the first a at 6
and the last one at 28. The first vowel is the o of
Fortran at position 2, and the last is the e that
ends language, at position 30. The set passed to
verify contains the lowercase letters and a space, so the first
character that does not belong to it is the capital F at position
1. Searching is case sensitive throughout, which is why the capital had to be
left out of the set.
$ gfortran s4.f90 -o s4 $ ./s4 index of "is": 9 index of "a": 6 last "a": 28 first vowel: 2 last vowel: 30 first other: 1
Character codes, repeat and building strings
Every character has a numeric code. iachar returns the code of a
one-character string and achar returns the one-character string
with a given code; both use the ASCII table, where A is 65,
a is 97 and the digits start at 48. repeat(s, n)
returns n copies of s, which is handy for
separators. Because a substring can stand on the left of an assignment,
strings can also be built character by character.
program s6
implicit none
integer :: i
print *, repeat('-', 20)
print *, repeat('ab', 3)
print *, 'length:', len(repeat('ab', 3))
print *, achar(72), achar(105)
print *, iachar('H'), iachar('i')
print *, 'codes:'
do i = 65, 70
print *, i, achar(i)
end do
end program s6
The first two lines produce a twenty-character rule and the repeated word
ababab. The codes 72 and 105 are the letters H and
i of Hi, and the loop walks from 65 to 70, printing
the first six capital letters with their codes. Since the codes of the letters
are consecutive, adding or subtracting a constant moves a letter through the
alphabet, which is the trick used in the example at the end of the article.
$ gfortran s6.f90 -o s6
$ ./s6
--------------------
ababab
length: 6
Hi
72 105
codes:
65 A
66 B
67 C
68 D
69 E
70 F
Deferred-length strings
Choosing a length in advance is awkward when the result grows as the program
runs. A variable declared character(len=:), allocatable has a
deferred length: the length is decided by each assignment, and the
variable is allocated with exactly as many characters as the right-hand side
has. len then reports the current length, and //
grows the string by producing a longer value that the variable takes over.
program s7
implicit none
character(len=:), allocatable :: msg, word
integer :: i
msg = 'Fortran'
print *, '[', msg, '] len =', len(msg)
msg = msg // ' 2018'
print *, '[', msg, '] len =', len(msg)
word = ''
do i = 1, 5
word = word // achar(64 + i)
end do
print *, '[', word, '] len =', len(word)
end program s7
The first assignment gives msg seven characters, with no padding,
and the second replaces it with a twelve-character string. The loop starts
from the empty string of length zero and appends one letter per pass, so the
length goes from 1 to 5 while the letters run from A to
E. Each concatenation creates a new value and copies the old
characters, which is fine for short strings but worth remembering when a loop
appends thousands of pieces.
$ gfortran s7.f90 -o s7 $ ./s7 [Fortran] len = 7 [Fortran 2018] len = 12 [ABCDE] len = 5
A worked example: the Caesar shift
A Caesar cipher replaces every letter by the one a fixed number of places
later in the alphabet, wrapping around from z to a.
The program below walks the text one character at a time, uses
iachar to test whether the character is a lowercase or an
uppercase letter, modulo to wrap the position inside the
alphabet, and writes the result back into a substring of the new string.
Digits, spaces and punctuation are copied unchanged.
program s8
implicit none
character(len=*), parameter :: text = 'Hello, World'
character(len=len(text)) :: shifted
integer :: i, c
do i = 1, len(text)
c = iachar(text(i:i))
if (c >= iachar('a') .and. c <= iachar('z')) then
shifted(i:i) = achar(iachar('a') + modulo(c - iachar('a') + 3, 26))
else if (c >= iachar('A') .and. c <= iachar('Z')) then
shifted(i:i) = achar(iachar('A') + modulo(c - iachar('A') + 3, 26))
else
shifted(i:i) = text(i:i)
end if
end do
print *, text
print *, shifted
end program s8
Shifting each letter three places turns Hello, World into
Khoor, Zruog: H becomes K,
e becomes h, and the two o letters
become r. The comma and the space are not in either letter
range, so the else branch copies them. Subtracting the code of
a converts a letter to a number from 0 to 25, which makes the
wrap with modulo simple.
$ gfortran s8.f90 -o s8 $ ./s8 Hello, World Khoor, Zruog
Next steps
The Fortran string processing article builds on these pieces: splitting text into words, reversing it, checking palindromes, replacing substrings and sorting words. The internal files article shows how a character variable can be used as a file, which is how numbers are turned into text and back. The arrays article explains the array constructors that appear in the sorting example, and the literals article covers the quoting rules for character constants.
Source
Fortran 2018 standard (J3/18-007r1)
Fortran-lang: learning resources
In this article we have declared strings of fixed and deferred length, joined and cut them, removed their padding, compared and searched them, and used character codes to build new text. The previous article, Fortran array arguments, explains how arrays reach procedures, which matters when a procedure takes a character array.
Author
List all Fortran tutorials.