ZetCode

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.

s1.f90
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.

s2.f90
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.

s3.f90
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.

s5.f90
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.

s4.f90
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.

s6.f90
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.

s7.f90
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.

s8.f90
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)

GNU Fortran manual

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

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Fortran tutorials.