Strings and concatenation
Text in Fortran has a fixed length and is padded with blanks, so joining two names needs care. trim, len_trim, adjustl and the // operator are the whole toolkit.
A fixed length, padded with blanks
A character variable is declared with a length, and that length is part of it: character(len=20) :: first always holds twenty characters. Assigning 'Grace' puts five letters in and fills the rest with blanks, and the variable is still twenty characters long.
Two functions then measure it differently. len(first) is the declared length, always 20. len_trim(first) is the length after trailing blanks are ignored, which is 5. When a program asks "how long is this name", it almost always means the second one.
Assigning a value longer than the declaration is worse than it sounds: the extra characters are dropped without a word. If a name might grow, give the field room at declaration time rather than discovering the limit later.
A dummy argument can be declared character(len=*), which means the length comes from whatever the caller passed. Inside the procedure, len then reports that length and len_trim the text without its padding. The star is for a dummy argument; an ordinary local character variable still needs a length in its declaration.
trim, adjustl and //
// joins two character values, and it joins them exactly as they are — padding included. first // last with two twenty-character variables gives a forty-character string with fifteen blanks in the middle where the first name ran out.
trim(value) removes the trailing blanks, so trim(first) // ' ' // trim(last) produces the name with one real space between the parts. adjustl(value) does the opposite housekeeping at the front, moving leading blanks to the end, which is what you want after reading text that was right-aligned.
Comparison accounts for the padding. 'abc' == 'abc ' is true, because the shorter side is padded before comparing, so exact-length matching is rarely a problem. Case still matters: 'Ada' and 'ada' are different strings, and there is no built-in uppercase function in the language itself.
adjustr is the mirror of adjustl: it moves trailing blanks to the front, which is useful when a value is meant to sit against the right edge of a field.
Building text that contains numbers
An internal write turns values into text: write(label, '(A,I0)') 'answer ', 42 fills label with answer 42. It is the same write used for the screen, aimed at a character variable instead, and chapter 8 covers the format part of it.
That is how a program builds a message, a file name or a line of a report without a string library. There is no string builder and no interpolation, just a fixed buffer, a format, and the knowledge that whatever is written is cut off at the buffer length.
An internal write does not resize its destination. If the formatted text is longer than the character variable, the extra characters are dropped, exactly as they are in an assignment. Size the buffer from the widest value the format can produce, not from the usual one.
Two names, joined properly
character(len=20) :: first, last
character(len=44) :: full
first = 'Grace'
last = 'Hopper'
print *, len(first), len_trim(first) ! 20 5
print *, '[' // trim(first) // ']' ! [Grace]
full = trim(first) // ' ' // trim(last)
print *, trim(full) ! Grace HopperA string is a buffer with a length
A character variable is a fixed-size buffer, not a growable string. character(len=20) :: name reserves twenty positions, and every operation works within that width: assignment pads or truncates, // produces a value whose length is the sum of both sides, and a substring such as name(1:3) reads positions 1 to 3 of the value already there.
That fixed width is why the length travels with the value. len reports the declared width, len_trim the width after trailing blanks, and index(text, pattern) searches inside a value and returns 0 when the pattern is absent. A loop that walks name(i:i) one character at a time is the standard way to inspect text, because there is no character type that can be indexed and resized at will.
Three string mistakes look like logic errors. trim returns a shorter value; it does not modify the variable you passed, so trim(name) on a line by itself does nothing. // needs a character value on both sides, so a number has to go through an internal write first. And a result longer than its destination is cut off silently — the extra characters are simply not stored.
Try these next
- Take the initials of a first and last name with
first(1:1)andlast(1:1). - Count how many times the letter
aappears in a word using adoloop andindex. - Build a label with an internal write and compare
len_trimwithlen.
See the padding, then remove it
Run it and look inside the square brackets: the blanks are real characters. Then change the declared lengths to 10 and see how the same lines behave, and join the names in the other order.
Initials, a label and a search
Run it and check the initials and the label. Then change the names to ones of different lengths and see which lines still work, and search for a letter that is not there.
A character assignment never fails: too long is silently truncated, too short is silently padded. Neither shows up as an error, so the length in a declaration is a decision, not a detail.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
For character(len=20) :: first holding the five letters "Grace", what is len(first)?
