2016-02-02 13 views
5

Mi piacerebbe leggere alcune stringhe di testo dalla riga di comando utilizzata per eseguire un programma. Sto utilizzando la subroutine interna GET_COMMAND_ARGUMENT in un programma che, in fondo è qualcosa di simile:Come ottenere argomenti da riga di comando di lunghezza sconosciuta in Fortran?

program test 
character(len=100) :: argument 
call GET_COMMAND_ARGUMENT(1,argument) 
print*, argument 
end program test 

Il problema qui è che sento che è un po 'pericoloso per impostare la lunghezza massima della stringa in fase di compilazione. Alcuni degli argomenti sono in genere file con il loro percorso, quindi potrebbero essere molto lunghi. Una soluzione che comporta l'impostazione statica della lunghezza a 1000 suona come una brutta soluzione.

Non esiste un modo più elegante in Fortran per definire una stringa in grado di contenere una catena di caratteri la cui lunghezza è nota solo in fase di esecuzione?

risposta

4

E 'possibile utilizzare quelli che vengono chiamati variabili carattere differito di lunghezza. Questi non hanno una lunghezza costante fissa e il loro uso può essere trovato in domande come a related one about data input.

Tuttavia, anche con una lunghezza variabile differita utilizzato come (per questo è la sintassi)

character(len=:), allocatable :: argument 
allocate(character(some_length) :: argument) ! For integer some_length 
call GET_COMMAND_ARGUMENT(1,argument) 
print*, argument 
end 

si deve ancora preoccuparsi di quello che dovrebbe essere some_length. Se scegliamo solo 100, torniamo al punto in cui eravamo.

Dobbiamo preoccuparci di questo perché get_command_argument non accetta un argomento di lunghezza differita e lo assegna alla lunghezza desiderata. Questo è

character(len=:), allocatable :: argument 
call GET_COMMAND_ARGUMENT(1,argument) ! Will argument be allocated in the subroutine? 
print*, argument 
end 

offre la risposta "no".

Venendo, quindi, a un modo per gestirlo, esaminiamo altri argomenti (facoltativi) su get_command_argument. In particolare, v'è uno chiamato length:

character(len=:), allocatable :: argument 
integer arglen 
call GET_COMMAND_ARGUMENT(1,length=arglen) 
allocate(character(arglen) :: argument) 
call GET_COMMAND_ARGUMENT(1,value=argument) 
print*, argument 
end 

Naturalmente, si potrebbe creare una subroutine involucro che ha fatto prendere una variabile carattere lunghezza differita definibili e ha fatto tutto quel lavoro.

+0

Il tuo approccio è molto migliore, in qualche modo ho dimenticato questo argomento. –

+0

Forse vale la pena notare che questo approccio funziona anche per 'get_environment_variable'. – francescalus

+0

Grazie, questo è di grande aiuto e in effetti risolve la domanda.Ho solo una piccola domanda, perché è necessario il piuttosto contorto 'allocate (character (some_length) :: argument)' invece del più semplice 'allocate (argument (some_length))' – Onturenio

1

Lascerò questo per completezza, potrebbe essere utile a qualcuno, ma la risposta di francescalus è molto meglio.

Fondamentalmente, basta leggerlo con una certa lunghezza predefinita, controllare la variabile STATUS e se non si adatta, riprovare.

Dal manuale gcc:

Se il recupero non riesce argomento, STATUS è un numero positivo; se VALUE contiene un argomento troncato della riga di comando, STATUS è -1; e altrimenti lo stato è zero.

Quindi:

character(len=:), allocatable :: argument 
integer :: stat, n 

n = 100 
allocate(character(n) :: argument) 

do 
    call GET_COMMAND_ARGUMENT(1,argument, status=stat) 
    if (stat>=0) exit 
    deallocate(argument) 
    n = n * 2 
    allocate(character(n) :: argument) 
end do 

if (stat>0) error... 

argument = trim(argument) 

print*, argument 
Problemi correlati