All examples presented in previous pages are simple. The number of variables and the number of edit descriptors are equal. In real applications, this is rarely the case. This page discusses a simple case; more complicated cases will be discussed later after more edit descriptors are covered.
Note that all edit descriptors discussed so far (i.e., I, F, E, L and A) are for printing the value of a variable or an expression. This makes our discussion easier. Recall that a WRITE always starts with a line. Here, a "line" should be interpreted as a buffer line discussed in the page of printer control.
When a formatted WRITE is executed, Fortran starts scanning the format from the left end (i.e., the edit descriptor next to the left parenthesis). For each variable or the result of an expression of the WRITE statement, Fortran uses the next available edit descriptor. Then, please remember the following:
The type of the value and the edit descriptor used to print it must match. Integers use edit descriptor I, reals use F or E, logicals use L, and character strings use A. Without observing this rule, your program may compile; but, it will cause execution error when that format is used.
In the example below, we have four variables to print. The first
one is Age whose type is INTEGER. Fortran starts
scanning the format from the left parenthesis and finds the first edit
descriptor I4. So, I4 is for Age.
Then, the next variable is Salary whose type is REAL.
To print it, Fortran finds the next edit descriptor F10.2.
Thus, F10.2 is for Salary. The next variable is
State whose type is CHARACTER. So, Fortran searches
for the next edit descriptor A. Thus, A (actually A8)
is for CHARACTER variable State. The next variable is
InState whose type is LOGICAL and the next editor descriptor
is L2. Thus, InState is printed using L2.
Now, all four variables are processed successfully into a buffer
line and printed with a printer.
CHARACTER(LEN=8) :: State = "Michigan"
INTEGER :: Age = 30
REAL :: Salary = 32165.99
LOGICAL :: InState = .TRUE.
WRITE(*,"(I4, F10.2, A, L2)") Age, Salary, State, InState
How about the following example? INTEGER variable Age is printed using I4, CHARACTER variable State is printed using F10.2. This is a mistake, because CHARACTER variables must be printed with the A edit descriptor and because the F descriptor can only print REAL values. Consequently, if you run this program, you will get a run time error when this WRITE is executed.
CHARACTER(LEN=8) :: State = "Michigan" INTEGER :: Age = 30 REAL :: Salary = 32165.99 LOGICAL :: InState = .TRUE. WRITE(*,"(I4, F10.2, A, L2)") Age, State, Salary, InState
Sooner or later you will ask this important question. We have two cases to consider:
This example has three variables and six edit descriptors in the format. This is a simple case. Here is the answer:INTEGER :: a = 1, b = 2, c = 4 CHARACTER(LEN=20) :: FMT = "(6I5)" WRITE(*,FMT) a, b, c
Based on this rule, variables a, b and c are printed with I5, I5 and I5. The three unused I5s are ignored.
Once all variables are processed, the WRITE statement completes and the content in the buffer line will be printed. All unused edit descriptors are simply ignored.
This example has five variables; but the format to print them has only two edit descriptors. Fortran starts scanning the format and assigns I4 to variable a and I3 to variable b. Then, it is the end of this format and three more variables are not yet printed. The rule for handling this case is the following:INTEGER :: a = 1, b = 2, c = 3, d = 5, e = 8 CHARACTER(LEN=20) :: FMT = "(I4, I3)" WRITE(*,FMT) a, b, c, d, e
The word "reuse" is the key here. Also, don't forget that once the end of the a format is reached, the content of the current buffer line is printed.
If all edit descriptors are used and there are unprinted variables, Fortran will print the current line and then the format until all variables are printed.
Let us continue with the above example. After printing
variable b using I3, the end of the format is
reached. Hence, the current line is printed and the format
is reused. This means Fortran will
rescan the format from the very
beginning. Therefore, variable c is printed with
I4 and variable d is printed with I3.
Then, the end of the format is reached. Therefore, this
(the second) line is printed and the format is reused.
The third time this format is scanned, variable e is
printed with I4. Then, all variables are printed and
the "unused" edit descriptors are ignored.
Therefore, three lines are generated. The first line
contains the values of a and b, the second line
contains the values of c and d, and the
third line contains the value of e. Note that the
first character of each line is used for printer control.
There are two more rules, one for those edit descriptors that do not require input or output values (i.e., nX, Tc, TLc, TRc and /), while the other for grouping. Click here to see the second rule, and here for the third.
Let us study why this is true. The format has five E17.7s. Therefore, after x(1) to x(5) are printed, the format reaches its end and Fortran prints the current line and reuses the format. Thus, x(6) to x(10) are printed on the second line, followed by x(11) to x(15) on the third line and so on until all n elements of x are printed.INTEGER, DIMENSION(1:100) :: x INTEGER :: n INTEGER :: i READ(*,*) n, (x(i), i=1, n) WRITE(*,"(5E17.7)") (x(i), i = 1, n)
When i is 1, we have two items to print, 1 and x(1), and they use I5 and E17.7, respectively. After these two items are printed, the end of format is reached, Fortran prints the current line and rescans the format. Then, the value of i is advanced to 2 and the next two items to be printed are 2 and x(2). Since now the format is reused, these two items use I5 and E17.7, respectively. Continuing with this manner, we know that each row contains two values, the values of i and x(i), printed with I5 and E17.7. The total number of lines is, of course, n.INTEGER, DIMENSION(1:100) :: x INTEGER :: n INTEGER :: i READ(*,*) n, (x(i), i=1, n) WRITE(*,"(I5, E17.7)") (i, x(i), i = 1, n)
Note that the program below prints the same output; but it uses a DO-END DO. Obviously, the version above is shorter.
INTEGER, DIMENSION(1:100) :: x INTEGER :: n INTEGER :: i READ(*,*) n, (x(i), i=1, n) DO i = 1, n WRITE(*,"(I5, E17.7)") i, x(i) END DO