Fred
Fred

Reputation: 579

Printing a Fortran array with an implicit loop

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

Answers (3)

jlokimlin
jlokimlin

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

wander95
wander95

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

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

Related Questions