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.
Your program should produce the following output report.1 ....5....0 5 4 7 2 -1 6 2 -3 4 -2 -3
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
Click here to download this program.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
The output of the program is:1 ....5....0 5 4 7 2 -1 6 2 -3 4 -2 -3
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)
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.Fmt2 = "(1X,A//1X,3A5/(1X,3I5))" WRITE(*,Fmt2) "Input Data", "No", "X", "Y", & (i, x(i), y(i), i = 1, Number)
Let me remind you that there is no need to have a / after 3I5 like this:
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:Fmt2 = "(1X,A//1X,3A5/(1X,3I5/))" WRITE(*,Fmt2) "Input Data", "No", "X", "Y", & (i, x(i), y(i), i = 1, Number)
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
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: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
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.(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
Of course, if we know the number of repetitions of 1X,I5, say 25, then the format can be rewritten as
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.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