web-dev-qa-db-fra.com

Convertir des entiers en chaînes pour créer des noms de fichiers de sortie au moment de l'exécution

J'ai un programme en Fortran qui enregistre les résultats dans un fichier. Au moment où j'ouvre le fichier en utilisant 

OPEN (1, FILE = 'Output.TXT')

Cependant, je souhaite maintenant exécuter une boucle et enregistrer les résultats de chaque itération dans les fichiers 'Output1.TXT', 'Output2.TXT', 'Output3.TXT', etc.

Existe-t-il un moyen simple dans Fortran de créer des noms de fichiers à partir du compteur de boucles i?

40
Alasdair

vous pouvez écrire sur une unité, mais vous pouvez aussi écrire sur une chaîne

program foo
    character(len=1024) :: filename

    write (filename, "(A5,I2)") "hello", 10

    print *, trim(filename)
end program

Veuillez noter (ceci est la deuxième astuce dont je parlais) que vous pouvez également créer une chaîne de format par programme.

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
48
Stefano Borini

Une solution beaucoup plus facile 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
17
Alejandro

Eh bien voici une fonction simple qui retournera la version de chaîne d'un nombre entier justifiée à gauche:

character(len=20) function str(k)
!   "Convert an integer to string."
    integer, intent(in) :: k
    write (str, *) k
    str = adjustl(str)
end function str

Et voici un code de test:

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
9
cyberthanasis

Je l'ai déjà montré ailleurs sur SO ( Comment utiliser une variable dans la déclaration de spécificateur de format? , ce n'est pas une copie IMHO exacte, mais je pense qu'il vaut la peine de la placer ici. Il est possible d’utiliser les techniques d’autres réponses pour cette question afin de créer une fonction simple.

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

que vous pouvez utiliser après sans vous soucier de l'ajustement et du réglage à gauche et sans écrire dans une variable temporaire:

OPEN(1, FILE = 'Output'//itoa(i)//'.TXT')

Il nécessite Fortran 2003 en raison de la chaîne pouvant être allouée.

5
Vladimir F

Pour une version abrégée . Si tous les indices sont inférieurs à 10, utilisez les éléments suivants:

do i=0,9
   fid=100+i
   fname='OUTPUT'//NCHAR(i+48) //'.txt'
   open(fid, file=fname)
   !....
end do

Pour une version générale:

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

C'est tout.

2
kayneo

Essayez ce qui suit:

    ....
    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
    ....

Où "..." signifie un autre code approprié à vos besoins.

0
Michael

J'ai déjà essayé @Alejandro et @ user2361779, mais cela me donne un résultat insatisfait tel que file 1.txt ou file1 .txt au lieu de file1.txt. Cependant, je trouve la meilleure solution:

...
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))
...

Explication:

par exemple. définir i = 10 et 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

Je pense que ceci est une solution la plus simple qui vous donne un nom de fichier de longueur dynamique sans aucun espace vide hérité d'un processus de conversion d'entier à une chaîne.

0
fronthem