Reputation: 579
This program unsuccessfully attempts to print an array on one line using an implicit loop in the format specification. It succeeds in doing the job with an explicit loop.
program cycle
implicit none
integer, dimension(5) :: a=(/1,2,3,4,5/), b=(/11,12,13,14,15/)
integer :: n, i
Print *, "Implicit loop"
print "(i0, 1x)", (a(i)*b(i), i=1,n)
Print *, "Explicit loop"
do i=1,n-1
write(*, '(i0, 1x)', advance = "no") a(i)*b(i)
end do
write(*, '(i0)') a(n)*b(n)
end program cycle
Here is the result:
Implicit loop
11
24
39
Explicit loop
11 24 39
How do I make the implicit loop print everything on a single line? Is it even possible? My attempts at inserting advance="no"
, surrounded by various commas and parentheses, have not worked.
Upvotes: 0
Views: 4695
Reputation: 593
First, non-advancing I/O may be performed only on an external file, and may not be used for namelist or list-directed I/O.
Second, a repeat count may be applied to a group of edit descriptors, enclosed in parentheses:
print '(4(i5,f10.3))', (bar(j), foo(j), j=1,4)
(for integer bar
and real foo
). This is equivalent to writing
print '(i5,f10.3,i5,f10.3,i5,f10.3,i5,f10.3)', (bar(j), foo(j), j=1,4)
Repeat counts such as this may be nested:
print '(2(2i5,2f10.3))', bar(1),bar(2),foo(1),foo(2),bar(3),bar(4),foo(3),foo(4)
Third, there are three ways in which a format
specification may be given. They are as follows:
(1) A default character expression (Best approach in my biased opinion):
print '(f10.3)', foo
write(*, '(f10.3)') foo
or
character(len=*), parameter :: FMT='(f10.3)'
print FMT, foo
write(*, FMT) foo
or
character, parameter :: FMT_ARRAY(*)=[ '(','f','1','0','.','3',')' ]
! Elements of an array expression are concatenated.
print FMT_ARRAY, foo
write(*, FMT_ARRAY) foo
or
character(4) :: fmt_1(10)
character(3) :: fmt_2(10)
integer :: i, j
fmt_1(10) = '(f10'
fmt_2(3) = '.3)'
i = 10
j = 3
! Format is built dynamically at execution time from various components.
print fmt_11(i)//fmt_2(j), foo
write(*, fmt_11(i)//fmt_2(j)) foo
(2) An asterisk (Only use this in the testing/development stages of your code):
print *, foo
write(*,*) foo
(3) A statement label (Not today Satan! There is no place for this in 2016):
print 42, foo
write(*, 42) foo
42 format(f10.3)
Upvotes: 0
Reputation: 1366
At the moment, I cannot post comments because I have less reputation, so writing it as an answer. Vladimir's answer is perfect. But to add to that answer, you could also do the following:
integer, parameter :: n=5 ! this line was missing in the question
write(fmt, 5)n , "(i0, 1x)"
5 format('(', I2, A9, ')')
write(*,*)"Implicit loop, formatted"
write(*, fmt) (a(i)*b(i), i=1,n)
For the explicit loop you can do the following in Fortran 2003 or later using new_line:
Print *, "Explicit loop 2"
do i=1,n ! notice the loop ends at 'n'
write(*, '(i0, 1x)', advance = "no") a(i)*b(i)
end do
write(*, *) new_line('')
This works on both intel and gfortran.
Upvotes: 0
Reputation: 60008
You format string only supports two items, an integer and a space. After that a new record is started and the format string is interpreted from the beginning.
(i0, 1x)
You must convert it to multiple items
(999(i0, 1x))
or (Fortran 2008)
(*(i0, 1x))
Then the parenthesis is used as many times as the number in the front says. *
means indefinitely. Of course only as long as there are items in the i/o list still to be processed.
Upvotes: 3