While implementing a simple echo program in the previous subsection, we accidentally stumbled on list-directed I/O, which allows you to read or write multiple variables on the same line. It’s called list-directed because of its functionality to consume and emit an arbitrary list of variables. For example, if you input a character string, an integer, and a real number on a single line, our next program will write out “‘User typed:’”, and print the variables on the remainder of the line:
Hello 42 3.14159 ❶
User typed: Hello 42 3.14159012 ❷
❶ Values for each variable typed in by the user
We’ll modify our program from listing 6.2 to accommodate all the variables, as shown in the following listing.
Listing 6.3 Using list-directed I/O to read and write an arbitrary number of variables
program read_write_list
implicit none
character(len=1000) :: text
integer :: a
real :: x
read *, text, a, x ❶
print *, 'User typed: ', trim(text), a, x ❷
end program read_write_list
❶ Reads a string, an integer, and a real from the terminal
❷ Writes the variables to the screen
What’s new here relative to listing 6.2 are the declarations for integer a and real x, and also that we are now using the default formatting in the read and print statements, indicated by a single asterisk (*). This does two things:
- The output will be written in a format that is compiler- and system-dependent. This means arbitrary leading and trailing spaces, and nonportable output precision for real numbers.
- It allows you to list any number of variables in the
readandprintstatements, including arrays or derived type components. For example, if you read an array of five elements, it would work the same as if you were to read five separate scalar variables. Likewise, writing out a derived type instance would write out each of its public components.
Using list-directed I/O is convenient for easy printing of values in your program. However, the form of the output isn’t portable across compilers and operating systems, and is thus not predictable. For these reasons, I only recommend using list-directed I/O during development, for quick and easy diagnosis or manual debugging.
Now run the read_write_list program again, and input data of different types (text, integer, or real) in a different order. What happens if you pass text to a variable that’s typed as an integer or a real? How about if you pass more than three items? Play with different inputs and explore what makes the program break and why.
Tip Use list-directed I/O only for quick-and-dirty tasks, such as manual debugging.
So far, we’ve assumed that the input data is coming from the keyboard, and the output data is going to the screen. Is this always the case, and how does the Fortran program know where the data comes from, and where it should go? By default, and in their basic form that we used in listings 6.2 and 6.3, the read statement will receive data from the standard input, and the print statement will send the data to the standard output. Let’s go into more detail about what they are and how we can use them for good.
Note When working with plain text data, read, print, and write statements always process one line at a time. To read or write multiple lines of data, invoke these statements as many times as needed.