Formats and edit descriptors
Last updated on 2026-02-21 | Edit this page
Overview
Questions
- How do I read input from the keyboard to my program?
- How can I control the format of input and output of various types?
Objectives
- Use the
readstatement analogously towriteto obtain input from the keyboard. - Learn how to combine edit descriptors to create a format specifier.
- Use format specifiers to control the appearance of output of the various types we have encountered.
Input and output
So far we have seen only output (via either print or
write). Input is via the read statement.
In very many respects, read looks much like
write, in that it takes the same arguments, including unit
number and format specifier. However, whereas write may
have an I/O list involving expressions, read must have only
the variables which will store the incoming values.
The standard input unit (input_unit from
iso_fortran_env in the above) is typically the keyboard (or
“screen”) for interactive use.
Format specifier
In addition to the list-directed or free-format
* specifier, a format may be a string literal, a fixed
character parameter, or a string constructed at run time. Some examples
are:
FORTRAN
read (*, *) var ! read using list-directed, or free format
print '(a)', "A string" ! character literal '(a)'
write (*, myformat) var ! character variable (or parameter)
write(unit = myunit) var ! unformatted (no format)
Output with a format specifier, either string or *, is
referred to as formatted I/O. This is to distinguish it from
unformatted I/O; this is essentially a direct dump of the
binary internal representation. For unformatted I/O the format specifier
is simply omitted.
Binary output can have its uses, but more portable and flexible methods of “fast” output are probably to be preferred (e.g., via a library such as HDF5). We will not consider unformatted output any further in this course.
Edit descriptors
A format specifier consists of a comma-separated list of edit descriptors enclosed in parentheses. The edit descriptors determine how the internal representation of data is translated or converted to characters which can be displayed.
The formal and exhaustive statement of exactly what is allowed in an edit descriptor is rather, well, exhausting. It is easier to consider some common examples of the three different types of descriptor.
Data edit descriptors
Data edit descriptors feature a single character describing the type data format wanted, and a literal integer part indicating the total field width, and number of decimals. These include
FORTRAN
iw ! integer width w characters
fw.d ! floating point number total width w and d decimal characters
ew.d ! scientific notation with total width w and d decimal characters
aw ! character string total width w
The width is the total width of the field, and must be wide enough to accommodate any leading signs, decimal points, or exponents. Where there is a w.d the d indicates the number of digits to appear after the decimal point.
Data edit descriptors should correspond to the relevant item in the io-list, based on position. Some simple examples are:
FORTRAN
integer :: ivar = 40
real :: avar = 40.0
print "( i10)", ivar ! produces "40" with 8 leading spaces
print "(f10.3)", avar ! produces "40.000" with 4 leading spaces
print "(e10.3)", avar ! produces "0.400e+02" with 1 leading space
For scientific notation, the exponent will appear either with two digits (“E+dd” or “E-dd”), or three digits for exponents greater than 99 (“+ddd” or “-ddd”).
If a first significant digit is required before the decimal point in
scientific notation (instead of a zero) the es edit
descriptor can be used instead of e; otherwise it’s the
same.
An engineering edit descriptor en is available. It also
acts like a standard e descriptor, but exponents are
limited to a subset …,-3,0,+3,+6,…, corresponding to standard SI
prefixes milli-, kilo-, mega-, and so on. There will be an appropriate
movement in the decimal point.
If an exponent greater than 999 is required, an optional
e descriptor for the exponent itself is available:
Note that an integer descriptor is allowed to be of the form iw.d, in which case leading zeros are added to pad to the width w, if required.
Character string edit descriptors
One can use a string literal as part of the edit descriptor itself, e.g.,
Control edit descriptors
There are a number of these. They do not correspond to an item in the
io-list, but alter the appearance of the output. The most
common is x which introduces a space (or blank). E.g.,
This will ensure at least one space between the two items in the list.
If a leading plus sign is wanted, use the sp control,
e.g.:
Exercise (2 minutes)
Exercise name
Compile and run the accompanying example1.f90 program, which provides some specimen formats. Some of the format specifiers have not been allowed a large enough width. What’s the result? What’s the solution?
Using gfortran produces the following output:
OUTPUT
Format i10: 40
Format i10.10: 0000000040
Format l10: F
Format f10.3: 40.000
Format e10.3: 0.400E+02
Format en10.3: 40.000E+00
Format a10: Hello
Format i1: *
Format f10.3: **********
Format e10.3: 0.180+309
Others:
Format sp,e12.3: +0.180+309
Format e12.3e4: 0.180E+0309
Where the format specifiers are too narrow, the output is reduced to
asterisks * in the space that has been provided. To fix
this, the specifiers need to be widened. For example, the integer
specifier on line 25 is i1, clearly not enough to print
-40. Making it i3 allows it to output.
The next failed output uses f10.3. It’s trying to print
a huge() number, where it was used to store the largest
possible number of the same type as the original avar. As a
real64, that’s approximately 1.80E+308. The
format specifier provides a width of 10 characters to print a number
with 309 digits (although we only have precision in the first 15 or so).
The f format specifier is very definitely unsuitable; one
of the e types such as es24.17 is much more
appropriate.
Repeat counts
For a larger number of items of the same type, it can be useful to specify a repeat count. Simply place the items to be repeated within parentheses and prefix a literal integer count to the format, e.g.:
Multiple subformats are comma-separated, much like the individual items, and subformats can also be nested. In this way, more complex formats can be constructed.
New lines
If no new line at all is wanted, one can use the
advance = no argument to write(),
e.g.:
Non-advancing output must not use list-directed I/O.
Statement labels
Formally, a format specifier may also be a statement label. For example,
Here, the statement at the line with label 100 is the
format keyword, which may be used to define a format
specifier. This is very common in older forms of Fortran. However, as
the reference and the statement can become widely separated, this can be
troublesome. However, statement labels are useful in other contexts, as
we will see when we come to error handling.
Exercise (5 minutes)
Experimenting with formats
Using the example1.f90 program, check what happens if there is a mismatch between the format specifier and the data type in the I/O list. Choose an example, and run the program.
What happens if the number of items in the io-list is larger than the number of edit descriptors?
Additional exercise. The b edit descriptor can be used
to convert integer values to their binary representation. For a 32-bit
integer type, the recommended descriptor would be b32.32 to
ensure the leading zeros are visible. You may wish to try this out.
Using the wrong type variable with a format specifier should still allow the code to compile, but you will receive a runtime error when it is encountered.
Any extra items in the io-list above what the format provides will not be printed.
- Control over the appearance of output is via the format specifier, which is a string.
- This similar in spirit to the format string provided to
printf()in C. - The use of a format allows predictable tabulation of output for human readers.