Преобразование целых чисел в строки для создания выходных имен файлов во время выполнения
У меня есть программа в Fortran, которая сохраняет результаты в файл. На данный момент я открываю файл, используя
OPEN (1, FILE = 'Output.TXT')
Однако теперь я хочу запустить цикл и сохранить результаты каждой итерации в файлах 'Output1.TXT'
, 'Output2.TXT'
, 'Output3.TXT'
и т.д.
Есть ли простой способ в Fortran для создания имен файлов из счетчика циклов i
?
Ответы
Ответ 1
вы можете записать в блок, но вы также можете написать строку
program foo
character(len=1024) :: filename
write (filename, "(A5,I2)") "hello", 10
print *, trim(filename)
end program
Обратите внимание (это второй трюк, о котором я говорил), что вы также можете программно создать строку формата.
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
Ответ 2
Более легкое решение 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
Ответ 3
Ну вот простая функция, которая вернет левую оправданную строковую версию целого числа:
character(len=20) function str(k)
! "Convert an integer to string."
integer, intent(in) :: k
write (str, *) k
str = adjustl(str)
end function str
И вот тестовый код:
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
Ответ 4
Я уже показывал это в другом месте на SO (Как использовать переменную в инструкции спецификатора формата?, а не точный дубликат IMHO), но я думаю, что это стоит чтобы разместить его здесь. Можно использовать методы из других ответов для этого вопроса, чтобы сделать простую функцию
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
который вы можете использовать после этого, не беспокоясь об обрезке и настройке слева и без записи во временную переменную:
OPEN(1, FILE = 'Output'//itoa(i)//'.TXT')
Он требует Fortran 2003 из-за выделяемой строки.
Ответ 5
Для сокращенной версии.
Если все индексы меньше 10, используйте следующее:
do i=0,9
fid=100+i
fname='OUTPUT'//NCHAR(i+48) //'.txt'
open(fid, file=fname)
!....
end do
Для общей версии:
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
Что все.
Ответ 6
Попробуйте следующее:
....
character(len=30) :: filename ! length depends on expected names
integer :: inuit
....
do i=1,n
write(filename,'("output",i0,".txt")') i
open(newunit=iunit,file=filename,...)
....
close(iunit)
enddo
....
Где "..." означает другой подходящий код для вашей цели.
Ответ 7
Я уже пробовал @Alejandro и @user2361779, но это дает мне неудовлетворенный результат, например file 1.txt
или file1 .txt
вместо file1.txt
. Однако я нахожу лучшее решение:
...
integer :: i
character(len=5) :: char_i ! use your maximum expected len
character(len=32) :: filename
write(char_i, '(I5)') i ! convert integer to char
write(filename, '("path/to/file/", A, ".dat")') trim(adjustl(char_i))
...
Пояснение:
например. установите i = 10
и write(char_i, '(I5)') i
char_i gives " 10" ! this is original value of char_i
adjustl(char_i) gives "10 " ! adjust char_i to the left
trim(adjustl(char_i)) gives "10" ! adjust char_i to the left then remove blank space on the right
Я думаю, что это самое простое решение, которое дает вам динамическое имя файла длины без каких-либо унаследованных пробелов от целого до строкового процесса преобразования.
Ответ 8
Чтобы преобразовать целое число в строку:
integer :: i
character* :: s
if (i.LE.9) then
s=char(48+i)
else if (i.GE.10) then
s=char(48+(i/10))// char(48-10*(i/10)+i)
endif
Ответ 9
Вот моя подпрограмма подхода к этой проблеме. он преобразует целое число в диапазоне 0: 9999 в качестве символа. Например, INTEGER 123 преобразуется в символ 0123. надеюсь, что это поможет.
P.S. - извините за комментарии; они имеют смысл на румынском языке: P
subroutine nume_fisier (i,filename_tot)
implicit none
integer :: i
integer :: integer_zeci,rest_zeci,integer_sute,rest_sute,integer_mii,rest_mii
character(1) :: filename1,filename2,filename3,filename4
character(4) :: filename_tot
! Subrutina ce transforma un INTEGER de la 0 la 9999 in o serie de CARACTERE cu acelasi numar
! pentru a fi folosite in numerotarea si denumirea fisierelor de rezultate.
if(i<=9) then
filename1=char(48+0)
filename2=char(48+0)
filename3=char(48+0)
filename4=char(48+i)
elseif(i>=10.and.i<=99) then
integer_zeci=int(i/10)
rest_zeci=mod(i,10)
filename1=char(48+0)
filename2=char(48+0)
filename3=char(48+integer_zeci)
filename4=char(48+rest_zeci)
elseif(i>=100.and.i<=999) then
integer_sute=int(i/100)
rest_sute=mod(i,100)
integer_zeci=int(rest_sute/10)
rest_zeci=mod(rest_sute,10)
filename1=char(48+0)
filename2=char(48+integer_sute)
filename3=char(48+integer_zeci)
filename4=char(48+rest_zeci)
elseif(i>=1000.and.i<=9999) then
integer_mii=int(i/1000)
rest_mii=mod(i,1000)
integer_sute=int(rest_mii/100)
rest_sute=mod(rest_mii,100)
integer_zeci=int(rest_sute/10)
rest_zeci=mod(rest_sute,10)
filename1=char(48+integer_mii)
filename2=char(48+integer_sute)
filename3=char(48+integer_zeci)
filename4=char(48+rest_zeci)
endif
filename_tot=''//filename1//''//filename2//''//filename3//''//filename4//''
return
end subroutine nume_fisier