Fortran Terminal Input/Output (I/O)

Write and Print

The generic Fortran output statement is write, which is an intrinsic subroutine. A write statement consists of the keyword write followed by (unit, format) and finally a list of variables and constants to be written, separated by commas.

    write (unit, format) value [, value ...]
            

The unit number is an integer value that tells the write statement where to send the output. Each unit number represents a file stream such as the standard input, standard output, or standard error. Opening files and creating additional file streams is covered in a later chapter. If a * is given for the unit number, the write statement writes to the standard output stream, which is normally connected to the terminal screen.

The format string is a template for how the output should look. It specifies how many characters and how many fractional digits should be printed for real numbers, for example. If a * is used in place of the format string, the write statement will use default formatting for all items printed, which is somewhat ugly, but functional.

After the (unit, format) come the items to be written. These may be variables of any type, string constants (characters between quotes), numeric constants, or algebraic expressions.

    real(8) :: height, width
    
    write (*,*) 'Please enter height and width on the same line:'
    read (*,*) height, width
    write (*,*) 'The area is ', height * width
            

The print statement is short-hand for writing to the standard output.

    print format, value [, value ...]
            

is equivalent to

    write (*, format) value [, value ...]
            

Example:

    real(8) :: height, width
    
    print *, 'Please enter height and width on the same line:'
    read (*,*) height, width
    print *, 'The area is ', height * width
            
Read

The read statement inputs values from a stream such as the standard input and places the values into variables. The components of a read statement are the same as for a write statement.

Providing a * as the unit number indicates that the read statement should read from the standard input stream, which is normally attached to the keyboard.

    real(8) :: height, width, area
    
    print *, 'Please enter the height and width on one line:'
    read (*, *) height, width
    area = height * width
    print *, 'The area is ', area
            

The read statement can also be written in short-hand form like the print statement:

    read *, height, width
            
The One Statement = One Line Rule

In Fortran, every read, write or print statement reads or writes one line of input or output. Unlike C, we cannot print part of a line with one statement and add to it with another statement. Fortran print and write statements always appends a newline character and read always reads to the end of an input line. Hence, the read statement above expects to find both height and width on the same line of input. That is, the user cannot press enter between the numbers.

Likewise, all of the output from a write or print statement will appear on the same line of output. The write or print statement will output all values, and send a newline character after the end of all output, so the next write or print will begin on a new line.

What is the output of the following?

    area = 4.0d0
    
    print *, 'The area is '
    print *, area
    print *, '.'
            
 The area is 
   10.000000000000000     
 .
            

To get everything on one line, we must do it in one print/write statement:

    print *, 'The area is ', area, '.'
            

With default formatting, it's not too pretty, but it is on one line as we desired.

 The area is    10.000000000000000      .
            
Standard Units

As mentioned earlier, using a * in place of the unit number tells the read statement to use the standard input stream and the write or print statement to use the standard output.

If you include the ISO_FORTRAN_ENV module in your program with:

    use ISO_FORTRAN_ENV
            

you can then use the actual unit numbers for the standard streams. The ISO_FORTRAN_ENV module provides the following named constants:

Table 18.4. Standard Stream Names

UnitStream
INPUT_UNITStandard Input
OUTPUT_UNITStandard Output
ERROR_UNITStandard Error

For the standard input and standard output, it's easier to type * than INPUT_UNIT or OUTPUT_UNIT. However, to write to the standard error unit, we must use ERROR_UNIT explicitly.

Example of Fortran input and output
!-----------------------------------------------------------------------
!   Description:
!       Find roots of a quadratic equation
!
!   Usage:
!       quadratic
!
!   Returns:
!       Nothing
!-----------------------------------------------------------------------

!-----------------------------------------------------------------------
!   Modification history:
!   Date        Name        Modification
!   2011-03-09  Jason Bacon Begin
!-----------------------------------------------------------------------

program quadratic
    ! Disable implicit declarations (i-n rule)
    implicit none
    
    ! Local variables
    real(8) :: a, b, c
    ! Use complex discriminant so we can get the square root
    ! even if it's negative.
    double complex :: discriminant_sqrt, root1, root2, two_a
    
    ! Input equation
    print *, 'Please enter the coefficients a, b, and c on one line:'
    read *, a, b, c

    ! Precompute terms that will be used more than once.
    ! Cast RESULT of all-double expression to complex so that only one
    ! promotion occurs.
    ! Convert 2a to complex now to avoid multiple promotions when
    ! computing the roots.
    discriminant_sqrt = sqrt(dcmplx(b * b - 4.0d0 * a * c))
    two_a = 2.0d0 * a
    
    ! Compute roots
    root1 = (-b + discriminant_sqrt) / two_a
    root2 = (-b - discriminant_sqrt) / two_a
    
    ! Output roots
    print *, 'The roots of ', a, 'x^2 + ', b, 'x + ', c, ' are:'
    print *, root1
    print *, root2
end program

Output from the program above:

 Please enter the coefficients a, b, and c on one line:
1 2 3
 The roots of    1.0000000000000000      x^2 +    2.0000000000000000
 x +    3.0000000000000000       are:
 ( -1.0000000000000000     ,  1.4142135623730951     )
 ( -1.0000000000000000     , -1.4142135623730951     )
            
Fortran Formatted I/O

As mentioned earlier, one of the asterisks in the write, print, and read statements tells the statement to use default formatting.

The default format is designed to use a consistent number of columns and present accurate information. This often leads to excessive white space and decimal places in the output:

    integer :: i = 5
    real(8) :: x = 5.0d0
    
    ! Statements
    print *, i, x
            
Output:             5   5.0000000000000000
Columns: 123456789012345678901234567890123
            

As you can see from the "ruler" below the output, the integer is printed across 12 columns, and the real(8) value across 21.

If we want to control the appearance of output or validate the format of input, we can replace the asterisk with a format specifier. The format specifier contains descriptors for each item to be printed, in the same order as the arguments to the read, write or print statement. The first descriptor describes the format of the first argument, and so on.

The most common descriptors are described in Table 18.5, “Common Format Descriptors”.

Table 18.5. Common Format Descriptors

DescriptorTypeFormat
IwAny integer typew columns total
Fw.dAny real typew columns total, d decimal places
Ew.dAny real typew columns total, d decimal places, scientific notation
AwStringw columns total
Gw.dAny real typeProgram chooses the best format

    integer :: i = 5, j = -6
    real(8) :: x = 5.0d0, y = -6.0d0
    
    ! Statements
    print '(i3, f10.2)', i, x

Output:   5      5.00
Ruler:  1234567890123

    write (*, '(i3, f10.2)'), i, x

Output:   5      5.00
Ruler:  1234567890123

    print '(i3, e10.2)', i, x

Output:   5  0.50E+01
Ruler:  1234567890123

    print '(i3, g10.2)', i, x

Output:   5   5.0
Ruler:  1234567890123

    print '(i3, i3, f10.2, f10.2)', i, j, x, y

Output:   5 -6      5.00     -6.00
Ruler:  12345678901234567890123456
            

If the width is non-zero and the value to be printed doesn't fit, the program will print a '*' instead of the number:

    integer :: i = 5, j = -6
    real(8) :: x = 5.0d0, y = -6.0d0
    
    ! Statements
    print '(i1, i1, f4.2, f4.2)', i, j, x, y

Output: 5*5.00****
Ruler:  1234567890
            

If the width is 0, the program will print the minimum number of digits needed to convey the correct value:

    integer :: i = 5, j = -6
    real(8) :: x = 5.0d0, y = -6.0d0
    
    ! Statements
    print '(i0, i0, f0.2, f0.2)', i, j, x, y

Output: 5-65.00-6.00
Ruler:  123456789012
            

The width and decimal places specifiers can be omitted for string values, in which case the program will print the string to its full length. This feature can be used with the zero-width descriptor for embedding numbers in text:

    integer :: i = 5, j = -6
    real(8) :: x = 5.0d0, y = -6.0d0

    ! Statements
    print '(a, i0, a, i0, a, f0.2, a, f0.2)', &
        'i = ', i, '  j = ', j, '  x = ', x, '  y = ', y

Output: i = 5  j = -6  x = 5.00  y = -6.00
Ruler:  1234567890123456789012345678901234
            

A format descriptor, or group of format descriptors in () can be preceded by an integer repeat count to shorten the format specifier:

    print '(i3, i3, f10.2, f10.2)', i, j, x, y

! Same as

    print '(2i3, 2f10.2)', i, j, x, y

    print '(a, i0, a, i0, a, f0.2, a, f0.2)', &
        'i = ', i, '  j = ', j, '  x = ', x, '  y = ', y

! Same as

    print '(2(a, i0), 2(a, f0.2))', &
        'i = ', i, '  j = ', j, '  x = ', x, '  y = ', y
            

Format specifiers can also be used in read statements. If a format specifier is used, then the input must match the format exactly, or an error will be generated. This is done to perform strict checking on input read from a file, if slight deviations in the format might indicate a problem with the data.

If we want to use the same format specifier in multiple print, read, or write statements, we can separate it out to a labeled format statement, and use the label in its place:

    print 10, 'i = ', i, '  j = ', j, '  x = ', x, '  y = ', y
    print 10, 'k = ', k, '  l = ', l, '  v = ', v, '  w = ', w

10  format (2(a, i0), 2(a, f0.2))
            
Practice

Note

Be sure to thoroughly review the instructions in Section 2, “Practice Problem Instructions” before doing the practice problems below.
  1. What is the "One statement = one line" rule?

  2. What are the names of the standard input, standard output, and standard error streams in Fortran when using ISO_FORTRAN_ENV?

  3. Write a Fortran program that asks the user their name, reads a line of text no longer than MAX_NAME_LEN from the standard input, and prints "Hello, " followed by the name to the standard output.

  4. Write a Fortran program that asks the user for the radius of a circle and the prints the area of the circle.

     What is the radius?
    10
     The area is    314.15926535897933      .