ZetCode

Reading input in Fortran

last modified November 14, 2026

A program that only prints results is a demonstration; a program that reads data is a tool. Fortran reads from the standard input, the stream of characters that comes from the keyboard or from a pipe, a channel that feeds another program's output into this one, and it writes to the standard output, the screen or a redirected file. The unit * in a read statement means the standard input, and the format * means list-directed input, where the compiler splits each line into fields and converts them to the types of the variables. This article shows how to read numbers, whole lines and tables, how to notice the end of the input with iostat, and how to keep a loop going until a special value arrives.

Reading numbers

The statement read (*, *) a, b takes two integers from the next line of input. List-directed input does not require fixed columns: the values may be separated by one or more blanks or by commas, and the compiler skips the blanks before each value. A prompt is just a write without a line break, produced by advance='no', which leaves the record open so that the answer appears after the question on the same line.

r1.f90
program r1
    implicit none
    integer :: a, b

    write (*, '(a)', advance='no') 'Enter two integers: '
    read (*, *) a, b
    write (*, '(/, a, i0, a, i0)') 'sum = ', a + b, ', product = ', a * b
end program r1

The transcript below feeds the line 3 4 into the program through a pipe, which is the same thing the program would see from a keyboard. The prompt is printed without a newline, the read consumes the two numbers, and the result starts on the next line because the format begins with a slash. The slash has to be there: without it the answer would continue on the prompt line, mixing with the question.

$ gfortran r1.f90 -o r1
$ printf '3 4\n' | ./r1
Enter two integers: 
sum = 7, product = 12

Reading a whole line

When the input is text rather than numbers, reading it as a number is impossible and reading it field by field is fragile. The reliable approach is to read the whole line into a character variable with the format '(a)', which copies the rest of the record without trying to interpret it. The line can then be inspected with the string functions, or parsed with an internal read, where the character variable itself supplies the fields, as described in the internal files article.

r2.f90
program r2
    implicit none
    character(len=80) :: line
    character(len=20) :: name
    integer :: age, ios

    write (*, '(a)', advance='no') 'name and age: '
    read (*, '(a)') line
    read (line, *, iostat=ios) name, age
    if (ios == 0) then
        write (*, '(/, a, a, i0, a)') trim(name), ' is ', age, ' years old'
    else
        write (*, '(/, a)') 'could not parse the line'
    end if
end program r2

The line Alice 30 is read whole, then the internal read splits it at the blank and converts the second field to an integer. In list-directed character input a blank ends the field, so Alice is stored and the rest of the line is left for the integer. With nonsense the second read fails, the status is not zero, and the program prints its own message instead of stopping with a runtime error.

$ gfortran r2.f90 -o r2
$ printf 'Alice 30\n' | ./r2
name and age: 
Alice is 30 years old

Reading until the end of the input

Real input has no known length, so a loop must stop when the data runs out. The iostat argument of read answers that question: zero means a value arrived, a negative value means the end of the input was reached, and a positive value means the text did not match the variables. A counted loop cannot do this job, since the number of values is exactly what is unknown, so the loop repeats until the status becomes non-zero.

r3.f90
program r3
    implicit none
    integer :: ios, count
    real :: x, total

    count = 0
    total = 0.0
    do
        read (*, *, iostat=ios) x
        if (ios /= 0) exit
        count = count + 1
        total = total + x
    end do
    write (*, '(a, i0)') 'values: ', count
    write (*, '(a, f8.2)') 'total:  ', total
    if (count > 0) write (*, '(a, f8.2)') 'mean:   ', total / count
end program r3

The input below has three numbers and one blank line. List-directed input skips the blank line, so three values are counted and the total is 8. The loop ends when the next read finds no more characters, which is the end-of-file condition with a negative status. The final if protects the mean against an empty input, where dividing by the count would produce a division by zero.

$ gfortran r3.f90 -o r3
$ printf '1.5\n2.5\n\n4\n' | ./r3
values: 3
total:      8.00
mean:       2.67

Prompts and a sentinel value

A sentinel is a value that has no meaning as data and marks the end of it: zero for a sum of positive numbers, minus one for a list of counts, an empty line for a list of names. The loop reads one value, tests it, and leaves before using it. Printing the value that was read makes the interaction with the program visible, which is useful while the input is being typed and harmless when it is piped from a file.

r4.f90
program r4
    implicit none
    integer :: n, total

    total = 0
    do
        write (*, '(a)', advance='no') 'next number (0 to stop): '
        read (*, *) n
        write (*, '(a, i0)') '  read ', n
        if (n == 0) exit
        total = total + n
    end do
    write (*, '(a, i0)') 'total: ', total
end program r4

Each pass prints the prompt without a newline, reads a number, and prints what it read, so every exchange occupies one line of the transcript. The numbers 4 and 5 are added and the final 0 stops the loop before it can change the total. This loop assumes that the input is well formed; if the read fails, the program stops with an error, which is acceptable for a small interactive tool but not for data from a file.

$ gfortran r4.f90 -o r4
$ printf '4\n5\n0\n' | ./r4
next number (0 to stop):   read 4
next number (0 to stop):   read 5
next number (0 to stop):   read 0
total: 9

Counting lines and words

Reading a line at a time and testing its status is the standard way to process a text file. The program below counts the lines and the words, where a word is a run of non-blank characters, as in the string processing article. The format '(a)' copies each record into the buffer, and len_trim gives the part that is not padding.

r5.f90
program r5
    implicit none
    character(len=120) :: line
    logical :: prev_blank
    integer :: ios, lines, words, i

    lines = 0
    words = 0
    do
        read (*, '(a)', iostat=ios) line
        if (ios /= 0) exit
        lines = lines + 1
        prev_blank = .true.
        do i = 1, len_trim(line)
            if (line(i:i) == ' ') then
                prev_blank = .true.
            else
                if (prev_blank) words = words + 1
                prev_blank = .false.
            end if
        end do
    end do
    write (*, '(a, i0)') 'lines: ', lines
    write (*, '(a, i0)') 'words: ', words
end program r5

The input has three lines, the last of them empty, and six words in total. A word is counted when a non-blank character follows a blank or starts the line, which is why prev_blank begins as true. The empty line counts as a line but adds no words. Because the loop reads whole records, the program does not care how many fields a line holds or what types they are.

$ gfortran r5.f90 -o r5
$ printf 'Fortran is fun\na compiled language\n\n' | ./r5
lines: 3
words: 6

Validating each line

Data from a file often contains a broken line, and a program that stops at the first one is not much use. The pattern is to read the line as text, try to parse it with an internal read, and use the status to decide between a result and a message. Each line is handled on its own, so one bad record does not prevent the rest from being processed, and the program can report exactly what it skipped.

r6.f90
program r6
    implicit none
    character(len=80) :: line
    character(len=20) :: name
    real :: s1, s2
    integer :: ios

    do
        read (*, '(a)', iostat=ios) line
        if (ios /= 0) exit
        if (len_trim(line) == 0) cycle
        read (line, *, iostat=ios) name, s1, s2
        if (ios /= 0) then
            write (*, '(a, a)') 'skipped: ', trim(line)
        else
            write (*, '(a, a, a, f5.1)') trim(name), ': ', 'average ', (s1 + s2) / 2.0
        end if
    end do
end program r6

The first two lines hold a name and two scores and produce an average. The third line is text that cannot be converted, so the program prints it with a skipped: prefix and continues. Blank lines are ignored by the cycle statement, which jumps to the next iteration. Reading the record into line first is what makes the recovery possible: the bad text is still available for the message, because the failed internal read left the original characters intact.

$ gfortran r6.f90 -o r6
$ printf 'Alice 80 90\nBob 70 60\nmalformed line\n' | ./r6
Alice: average  85.0
Bob: average  65.0
skipped: malformed line

Next steps

The formatted output article explains the formats used for the prompts and the results, and the internal files article covers the string-to-number conversion in detail. The string processing article shows how to split the lines further, and the files article replaces the standard input with a file opened by name.

Source

Fortran 2018 standard (J3/18-007r1)

GNU Fortran manual

Fortran-lang: learning resources

In this article we have read numbers and whole lines from the standard input, detected the end of the data with iostat, stopped a loop on a sentinel value, counted the lines and words of a text, and recovered from a line that could not be parsed. The previous article, Fortran formatted output, explains the formats that shape what the program prints while it reads.

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.