Reputation: 21
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/)
Upvotes: 2
Views: 155
Reputation: 32396
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.)
Upvotes: 3
Reputation: 21
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
Upvotes: 0