Convert integers to strings to create output filenames at run time
Solution 1
you can write to a unit, but you can also write to a string
program foo
character(len=1024) :: filename
write (filename, "(A5,I2)") "hello", 10
print *, trim(filename)
end program
Please note (this is the second trick I was talking about) that you can also build a format string programmatically.
program foo
character(len=1024) :: filename
character(len=1024) :: format_string
integer :: i
do i=1, 10
if (i < 10) then
format_string = "(A5,I1)"
else
format_string = "(A5,I2)"
endif
write (filename,format_string) "hello", i
print *, trim(filename)
enddo
end program
Solution 2
A much easier solution IMHO ...................
character(len=8) :: fmt ! format descriptor
fmt = '(I5.5)' ! an integer of width 5 with zeros at the left
i1= 59
write (x1,fmt) i1 ! converting integer to string using a 'internal file'
filename='output'//trim(x1)//'.dat'
! ====> filename: output00059.dat
Solution 3
Well here is a simple function which will return the left justified string version of an integer:
character(len=20) function str(k)
! "Convert an integer to string."
integer, intent(in) :: k
write (str, *) k
str = adjustl(str)
end function str
And here is a test code:
program x
integer :: i
do i=1, 100
open(11, file='Output'//trim(str(i))//'.txt')
write (11, *) i
close (11)
end do
end program x
Solution 4
I already showed this elsewhere on SO (How to use a variable in the format specifier statement? , not an exact duplicate IMHO), but I think it is worthwhile to place it here. It is possible to use the techniques from other answers for this question to make a simple function
function itoa(i) result(res)
character(:),allocatable :: res
integer,intent(in) :: i
character(range(i)+2) :: tmp
write(tmp,'(i0)') i
res = trim(tmp)
end function
which you can use after without worrying about trimming and left-adjusting and without writing to a temporary variable:
OPEN(1, FILE = 'Output'//itoa(i)//'.TXT')
It requires Fortran 2003 because of the allocatable string.
Solution 5
For a shorten version. If all the indices are smaller than 10, then use the following:
do i=0,9
fid=100+i
fname='OUTPUT'//NCHAR(i+48) //'.txt'
open(fid, file=fname)
!....
end do
For a general version:
character(len=5) :: charI
do i = 0,100
fid = 100 + i
write(charI,"(A)"), i
fname ='OUTPUT' // trim(charI) // '.txt'
open(fid, file=fname)
end do
That's all.
Comments
-
Alasdair almost 2 years
I have a program in Fortran that saves the results to a file. At the moment I open the file using
OPEN (1, FILE = 'Output.TXT')
However, I now want to run a loop, and save the results of each iteration to the files
'Output1.TXT'
,'Output2.TXT'
,'Output3.TXT'
, and so on.Is there an easy way in Fortran to constuct filenames from the loop counter
i
? -
F'x over 14 yearsTwo comments: - you don't have to discriminate on the value of I; the format (I0) will output an integer without any space; also, if you want a fixed width and padding with zeroes (like "output001.txt"), you need to used (I0.3) - the format (A5I2) is not valid Fortran according to any norm, as format specifiers are to be separated by commas: (A5,I2)
-
Stefano Borini over 14 yearsWell, it was for educational purposes, not intended to be the solution. In general I use the padding zeros (as it sorts nicely), but the I0 thingie I didn't know about. Thanks!! (fixed the commas, I think my style was the old one, still accepted)
-
High Performance Mark almost 12 yearsThis is a very bad answer. As the accepted answer already shows Fortran provides a mechanism for writing the value of an integer into a character variable; all this fiddling around with encoding and decoding character indices is a horrid hack which serves no useful purpose.
-
gluuke over 10 years@F'x thanks for the comment, really useful. Indeed even trim won't work if the number k of digits is not equal to "(Ik)" in the format, so just use "(I0)" so that one doesn't need to adapt the format.
-
ryanjdillon about 10 yearsmay just be my compiler, but i was needed to declare a character variable for the output string written to (i.e.
character(5) x1
). thanks! -
francescalus almost 9 yearsUsing
I0
as the edit descriptor would be much simpler:write(filename, '("path/to/file/", I0, ".dat")') i
. This is mentioned previously in this question only in comments, so perhaps could be added. -
fronthem almost 9 yearsThank you @francescalus, I didn't notice that comment. Then left my answer to be an alternative solution. it may be useful in some case.
-
Osman Mamun almost 9 yearsThere should be no comma after after the closing parentheses in write statement. (( write(charI,"(A)") i )) Thanks, I am using this suggestion.
-
PVitt about 8 years@HighPerformanceMark Regarding his name, this code looks quite reasonable.
-
kayneo over 7 yearsThe default is no comma, but I found it works well if the additional comma added, similar as ((print *, i))
-
Manuel Pena over 5 yearsThere is not A0 as the counterpart of I0, right? (meaning a character string with any padding)
-
Jean-Claude Arbaut over 3 years@ManuelPena "w shall be zero or positive for the I, B, O, Z, D, E, EN, ES, EX, F, and G edit descriptors. w shall be positive for all other edit descriptors." (Fortran 2018, where w is the width parameter). However, the width is not mandatory for the A edit descriptor, and if omitted, the length of the character string is used instead. But bear in mind that this length includes any trailing space: if you want to remove them from the output, use the A edit descriptor (without length parameter) and pass
trim(s)
instead ofs
. You may also want toadjustl
.