1

I want to make a variable format for my "write" statement. To do so, I wrote a small program (nvari is the variable):

program VariableFormat
  implicit none

  integer              :: x = 1,y = 2, z = 3, i, nvari
  double precision     :: pi = 3.14
  integer, allocatable :: var(:)
  integer              :: A(3) = (/1,2,3/)
  character(100)       :: fmt,fmt2,str1,str2,str3

  print*, size(A)
  allocate(var(size(A)))
  do i = 1, size(A)
     var(i) = A(i)
  end do
  nvari = 2
  !
  ! first part
  !
  fmt = '(a,f4.2)'
  write(*,fmt) "The value of pi is ", pi
  !
  ! second part
  ! 
  write (str1, "(1A2,1I1,1A1,1I2,1A1)") "'(", 3, "I", 15, ","
  print*, str1
  write(str2,'(I10)') nvari
  print*, str2
  write (str3, "(1A1,1I2,1A2)") "I", 15, ")'"
  print*, str3
  fmt2 = trim(adjustl(str1))//trim(adjustl(str2))//trim(adjustl(str3))
  print*, fmt2
  write(*,fmt2) x,y,z,(var(i),i=1,nvari)
  
end program VariableFormat

First question: It can be seen that fmt2 is similar to fmt in the sense that in both we have '(X,Y)'. However, while the first part of the code is executed correctly, for the second part, I have the error:

At line 32 of file VariableFormat.F90 (unit = 6, file = 'stdout')
Fortran runtime error: Missing initial left parenthesis in format
'(3I15,2I15)' 

I don't understand which parenthesis is missing as fmt2 is similar to fmt. To execute my program I use the gfortran compiler: gfortran -o binary_VariableFormat VariableFormat.F90 and then:./binary_VariableFormat

Second question: Is there a way to write fmt2 in a more compact way?

Ian Bush
  • 6,996
  • 1
  • 21
  • 27
user790082
  • 69
  • 5
  • For your second question (please try to stick to one question per post unless very closely related), you might find inspiration in [this other question](https://stackoverflow.com/q/72606446/3157076). – francescalus Jan 25 '23 at 18:32

1 Answers1

1

This is perhaps more a misunderstanding about character variables and literal constants than about formats.

In

fmt = '(a,f4.2)'

we have the character variable's name (fmt) on the left-hand side of the assignment and the value to assign on the right. '(a,f4.2)' is a literal character constant and its value is given to fmt.

The two, matching, ''s act as delimiters for the value of the constant: they are not themselves part of the value.1 The value of the literal constant is (a,f4.2). Go on, print the value of fmt to check. (One actually has to do something quite different to get the value of a character variable with delimiters.)

A character value in a format must be something like (...): the first non-blank value must be a (. Because you've set the value to be like '(...)' the compiler is (quite rightly) complaining.

Where we have something like

write(str2,'(I10)') nvari

we are using this literal constant which has value (I10) not '(I10)'. If we instead had

write(str2,"'(I10)'") nvari

we'd see exactly the same complaint (or perhaps a complaint when compiling instead of running).

Finally, note that when using a FORMAT statement (many here really don't like such things), we'd not have these delimiters at all:

format (I10)   ! Correct
format '(I10)' ! Badly wrong

1 Similarly, if we have literal constants used like

complex :: a = (1., 2.)
integer :: i = INT(B'001')

the delimiters for the complex and BOZ literal constants are not part of the value. Equally in an array constructor like [0,1,2,3] the square brackets are a delimiter part of the syntax rather than the value.

francescalus
  • 30,576
  • 16
  • 61
  • 96