2009-08-11 10 views

risposta

48

è possibile scrivere ad un'unità, ma si può anche scrivere in una stringa

program foo 
    character(len=1024) :: filename 

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

    print *, trim(filename) 
end program 

Si prega di notare (questo è il secondo trucco stavo parlando) che si può anche costruire una stringa di formato di programmazione.

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 
+12

Due commenti: - non c'è bisogno di discriminare sul valore di I; il formato (I0) restituirà un intero senza spazio; inoltre, se vuoi una larghezza fissa e padding con zero (come "output001.txt"), devi usare (I0.3) - il formato (A5I2) non è valido per Fortran secondo alcuna norma, poiché gli specificatori di formato sono da separare da una virgola: (A5, I2) –

+0

Bene, era per scopi didattici, non inteso come soluzione. In generale io uso gli zeri padding (come ordina gentilmente), ma i thingie I0 di cui non ero a conoscenza. Grazie!! (corretto le virgole, penso che il mio stile fosse quello vecchio, ancora accettato) –

+0

@ F'x grazie per il commento, davvero utile. Infatti anche il trim non funzionerà se il numero k di cifre non è uguale a "(Ik)" nel formato, quindi basta usare "(I0)" in modo che non sia necessario adattare il formato. – gluuke

-4

Ecco il mio approccio di subroutine a questo problema. trasforma un intero nell'intervallo 0: 9999 come carattere. Ad esempio, INTEGER 123 viene trasformato nel carattere 0123. spero che sia d'aiuto.

P.S. - scusa per i commenti; hanno un senso in rumeno: 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 
+6

Questa è una pessima risposta. Come la risposta accettata mostra già, Fortran fornisce un meccanismo per scrivere il valore di un intero in una variabile di carattere; tutto questo traboccare con gli indici dei caratteri di codifica e decodifica è un horrid hack che non serve a nulla. –

+2

@HighPerformanceMark Per quanto riguarda il suo nome, questo codice sembra abbastanza ragionevole. – PVitt

13

Una soluzione molto più 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 
+0

CORREZIONE: filename = 'output' // trim (x1) // '. Dat' – Alejandro

+0

potrebbe essere solo il mio compilatore, ma dovevo dichiarare una variabile di carattere per la stringa di output scritta su (cioè 'character (5) x1 '). Grazie! – ryanjdillon

8

Beh qui è un semplice funzione che restituisce la versione stringa di sinistra giustificato di un numero intero:

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

Ed ecco un codice di prova:

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 
2

Per una versione abbreviata. Se tutti gli indici sono più piccoli di 10, quindi utilizzare il seguente:

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

Per una versione generale:

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 

Questo è tutto.

+0

Non dovrebbe esserci alcuna virgola dopo le parentesi di chiusura nell'istruzione di scrittura. ((scrivi (charI, "(A)") i)) Grazie, sto usando questo suggerimento. – mamun

+0

L'impostazione predefinita non è una virgola, ma ho trovato che funziona bene se la virgola aggiuntiva aggiunta, simile a ((print *, i)) – kayneo

0

Ho provato già @ Alejandro e @ utente2361779 ma mi dà un risultato insoddisfatto come file 1.txt o file1 .txt anziché file1.txt. Tuttavia ho trovato la soluzione migliore:

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

Spiegazione:

esempio set i = 10 e 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 

Penso che questa sia una soluzione più semplice che ti danno un nome di file di lunghezza dinamica senza precedenti spazi vuoti da intero a processo di conversione di stringhe.

+1

Utilizzare 'I0' come descrittore di modifica sarebbe molto più semplice:' scrivi (nomefile, '("percorso/su/file /", I0, ".dat") ') i'. Questo è menzionato precedentemente in questa domanda solo nei commenti, quindi forse potrebbe essere aggiunto. – francescalus

+0

Grazie @francescalus, non ho notato quel commento. Quindi ho lasciato la mia risposta per essere una soluzione alternativa. potrebbe essere utile in alcuni casi. – fronthem

2

L'ho già mostrato altrove su SO (How to use a variable in the format specifier statement?, non un duplicato esatto IMHO), ma penso che valga la pena inserirlo qui. E 'possibile utilizzare le tecniche di altre risposte per questa domanda per fare una semplice funzione

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 

che può essere utilizzato dopo senza preoccuparsi di rifinitura e di sinistra ed aggiustaggio, senza scrivere a una variabile temporanea:

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

Richiede Fortran 2003 a causa della stringa assegnabile.

-1

Per convertire un intero in una stringa:

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 
+0

Cosa succede se 'i' è grande? – francescalus

Problemi correlati