0

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.

6
  • 2
    I'm surprised that program prints anything at all since n is never given a value. Commented Aug 17, 2016 at 18:59
  • Your array construction hurts my eyes. Since a is never modified, why not use integer, parameter :: a(*)= [1, 2, 3, 4, 5]. Commented Aug 18, 2016 at 0:54
  • The omission of n is indeed a mistake. Here is my command line for compiling an executable called m.exe under WIndows: gfortran mullist2q2.f90 -o m My question: are there any compiler flags I should be using to catch such mistakes? Are there any tools you recommend for checking Fortran source? Commented Aug 18, 2016 at 8:04
  • jlokimlin, thanks for the square brackets. I'm trying to use a 'modern subset' of Fortran. I find "Guide to Fortran 2008 Programming" by Walter S. Brainerd a valuable, but concise guide. He shows square brackets too. I pick up bad habits surfing the internet for code. Commented Aug 18, 2016 at 8:17
  • @wander95, please be very careful when editing code in questions. Yes, the missing n is important, but the change you made left the code uncompilable. Although you didn't have comment privelege at that time, such things are best done (as with High Performance Mark's comment) by requesting clarification from the author. Commented Aug 18, 2016 at 8:33

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, Vladimir. I am one step further in learning Fortran. That is exactly what I was struggling to do.
0

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.

4 Comments

I wouldn't really introduce a FORMAT statement in year 2016 if it is not present in the original code. I find it quite difficult to read especially in this combination when writing to another format string. But more importantly, it is just more work, which is not necessary, a large constant suffices, so why bother.
Thanks Wander95, I ran your code and it works. The interesting property of both your code and Vladimir's amendment to my implicit loop is the lack of a final space at the end. To achieve the same thing with the explicit loop I have the second write statement. I assume this property is standard behaviour and not compiler-dependent. Is this true?.
I have added an example of a Explicit loop where you write the newline character using Fortran 2003's new_line().
To advance to the next record after some non-advancing output just use write (unit, "()"). Writing new_line() to a sequential formatted file doesn't make sense in the general case.
0

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)

4 Comments

Did you mean to answer here? This doesn't seem terribly relevant to the question.
@francescalus It was included for the sake of completeness. Most new Fortraners (including myself at one time) don't know any alternatives to labeled format statements or that non-advancing I/O is restricted to external files.
Appreciate the examples you gave, clarifies the somewhat murky formatting topic for me. One area I still need help on: I keep getting -.462 instead of -0.462 for real numbers. How do I get the single leading zero?
@Fishsticks Getting a single leading zero depends on the precision that you're using. That is, for 32-bit single (default) precision print '(e13.6e2)', x, for 64-bit double precision print '(e23.15e3)', x, and if your compiler supports 128-bit quad precision, print '(e42.33e4)', x. You can get storage-based kind parameters from the intrinsic module ISO_Fortran_env.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.