WARNING: This example assumes spaces are ignored for the I and F descriptors and the output is sent to a printer.
Write a Fortran to read in two sequences of numbers and computes their inner product.
Suppose we have an input like the following. The first line gives the number of input values. Each of the input line has two fields with 10 positions each. You should use only one format to read all data items.
1
....5....0
5
4 7
2 -1
6 2
-3 4
-2 -3
Your program should produce the following output report.
1 1 2 2 3
....5....0....5....0....5....0
Input Data
No X Y
1 4 7
2 2 -1
3 6 2
4 -3 4
5 -2 -3
Input product = 32
PROGRAM InnerProduct
IMPLICIT NONE
INTEGER, PARAMETER :: SIZE = 50
INTEGER :: Number, Sum, i
INTEGER, DIMENSION(1:SIZE) :: x, y
CHARACTER(LEN=80) :: Fmt1, Fmt2, Fmt3
Fmt1 = "(I5/(2I5))"
Fmt2 = "(1X,A//1X,3A5/(1X,3I5))"
Fmt3 = "(/1X, A, I7)"
READ(*,Fmt1) Number, (x(i), y(i), i = 1, Number)
WRITE(*,Fmt2) "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number)
Sum = 0
DO i = 1, Number
Sum = Sum + x(i)*y(i)
END DO
WRITE(*,Fmt3) "Input product = ", Sum
END PROGRAM InnerProduct
Click here to download this program.
1
....5....0
5
4 7
2 -1
6 2
-3 4
-2 -3
The output of the program is:
1 1 2 2 3
....5....0....5....0....5....0
Input Data
No X Y
1 4 7
2 2 -1
3 6 2
4 -3 4
5 -2 -3
Input product = 32
Since I5 is used only once and 2I5 is used a number of times, to repeat 2I5, what we have to do is enclosing 2I5 in a pair of parenthesis: (I5/(2I5)). By the way, (I5/2(I5)) would do the job (why?); but I prefer (I5/(2I5)). So, the following is the READ statement and the format:
Fmt1 = "(I5/(2I5))" READ(*,Fmt1) Number, (x(i), y(i), i = 1, Number)
Fmt2 = "(1X,A//1X,3A5/(1X,3I5))"
WRITE(*,Fmt2) "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number)
1X,A prints the title Input Data. Then, //
produces a blank line between the title and the table heading.
No, X and Y are printed with 1X,3A5.
The next / terminates the heading line, meaning that
subsequent output starts with the next output line.
Now, we see the grouping again, which means 1X,3I5 will
be used over and over until all data items are printed.
Let me remind you that there is no need to have a / after 3I5 like this:
Fmt2 = "(1X,A//1X,3A5/(1X,3I5/))"
WRITE(*,Fmt2) "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number)
Reason? Recall that when the closing right parenthesis is reached,
Fortran always terminates the current input or output line
and all subsequent input and output will be on the next line.
If we have (1X,3I5/), this means after printing three
integers, the current line is terminated and output will be
performed on the next line. Then, Fortran
sees the closing right parenthesis, which terminates the current
line. Therefore, this line has nothing but spaces. This implies
that the table is double-spaced:
1 1 2
....5....0....5....0
Input Data
No X Y
1 4 7 <--- 1X,3I5/
<--- printed due to end of format
2 2 -1 <--- 1X,3I5/
<--- printed due to end of format
3 6 2 <--- 1X,3I5/
<--- printed due to end of format
4 -3 4 <--- 1X,3I5/
<--- printed due to end of format
5 -2 -3 <--- 1X,3I5/
<--- printed due to end of format
After the table is printed, printing stops at the last line of the table and subsequent printing should be below this last line. Therefore, the above format starts with / so that we will have a blank line between the table and the result. Thus, this tells you that / can be used to produce blank lines.Fmt3 = "(/1X, A, I7)" WRITE(*,Fmt3) "Input product = ", Sum
Fmt = "(1X,A//1X,3A5/(1X,3I5)//1X, A, I7)"
WRITE(*,Fmt) "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number), &
"Input product = ", Sum
Note that we have // between (1X,3I5) and
1X,A,I7. This is because we need a blank line between the
table and the result. This format does not work, simply because
it is equivalent to the following:
(1X, A // 1X, 3A5 / 1X, 3I5 // 1X, A, I7 /
1X, 3I5 // 1X, A, I7 /
1X, 3I5 // 1X, A, I7 /
.....)
WRITE(*,Fmt) "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number), &
"Input product = ", Sum
As you can see, 3I5 is followed by a blank line, followed
by 1X, A, I7. This is incorrect since A is not
allowed to print INTEGERs.
Of course, if we know the number of repetitions of 1X,I5, say 25, then the format can be rewritten as
Fmt = "(1X,A//1X,3A5/25(1X,3I5)//1X, A, I7)"
^^
^^------ 25 is added here
WRITE(*,Fmt) "Input Data", "No", "X", "Y", &
(i, x(i), y(i), i = 1, Number), &
"Input product = ", Sum
However, this change is unwise, because the next run of this
program, we may have more than or less than 25 data items and
this makes the format not working! To overcome this problem,
we need more powerful techniques (e.g., internal files),
which will be discussed later.
Click here for some details.