2

Can I replace an explicit initialization of a character array, like this:

character(len=8), dimension(5) :: names  = (/'ens_0001','ens_0002','ens_0003','ens_0004','ens_0005'/)

with an implied do-loop construct? Something with a formatted write statement?

character(len=8), dimension(5) :: names  =  write? other magic? 'ens_',i4.4', ... (/j=1,5/) 

2 Answers 2

3

The question is essentially equivalent to the alternative question: can I convert an integer to a character in a constant expression?

Yes you can, but you are limited in how this can be done.

One way would be:

  implicit none

  character, parameter :: digit(0:*) = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
  integer i  
  character :: number(3) = [(digit(i), i=2, 8, 3)]

  print '(A)', number
end

And there are other ways, such as using ACHAR.


Once you know how to get a single character you can use the natural extensions, such as

  character(8) :: label(5) = 'ens_000'//[(digit(i), i=1, 5)]

And so on, extending to tens, hundreds and more if you find the appropriate logic:

  integer j
  character(2), parameter :: twodigit(0:*) = [((digit(i)//digit(j), j=0,9), i=0,9)]
 
  character(8) :: label(12) = 'ens_0'//[(twodigit(i), i=11, 22)]

You cannot use an internal write (or other executable statement) or a user-defined function in the constant expression.

This does quickly become silly as the number of digits increases, but it's also possible to use indexes (or substrings) and arithmetic:

  character(8) :: label(12) = 'ens_0'//[(digit(i/10)//digit(mod(i,10)), i=11, 22)]

(Recall if using them that substrings are always 1-indexed.)

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

Comments

0

Thanks Francescalus for the pointers! That really helped. The final solution is posted below. I never actually stated this detail, but I had to go from ens_0001 to ens_1200, so the nested implicit do-loops are 4 deep!

program foo
  implicit none

  integer i,j,k,l
  character, parameter :: digit(0:*) = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
  character(4), parameter :: fourdigit(0:*) = [((((digit(i)//digit(j)//digit(k)//digit(l), l=0,9), k=0,9), j=0,9), i=0,9)]

  character(8) :: label(1200) = 'ens_'//[(fourdigit(i), i=1, 1200)]
  print '(A)', label
end

1 Comment

If an answer solved your problem, consider accepting it. I suggest taking the Welcome tour.

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.