2016-02-02 7 views
5

Ich möchte einige Textzeichenfolgen von der Befehlszeile lesen, die zum Ausführen eines Programms verwendet wird. Ich bin das interne Unterprogramm mit GET_COMMAND_ARGUMENT in einem Programm, das im Grunde so etwas wie ist:Wie erhalten Sie Befehlszeilenargumente unbekannter Länge in Fortran?

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

Das Problem hier ist, dass ich glaube, es ist ein bisschen gefährlich, die maximale Länge der Zeichenfolge bei der Kompilierung zu setzen. Einige der Argumente sind normalerweise Dateien mit ihrem Pfad, daher können sie sehr lang sein. Eine Lösung, bei der die Länge statisch auf 1000 festgelegt wird, klingt wie ein hässlicher Workaround.

Gibt es in Fortran nicht eine elegantere Möglichkeit, eine Zeichenfolge zu definieren, die eine Kette von Zeichen enthalten kann, deren Länge nur zur Laufzeit bekannt ist?

Antwort

4

Es ist möglich, zu verwenden, was latente Länge Zeichenvariablen genannt werden. Diese haben keine feste konstante Länge und ihre Verwendung kann in Fragen wie a related one about data input gefunden werden.

Doch selbst mit einem latenten Länge Variable verwendet wie (hierfür ist die Syntax)

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

man noch hat Grund zur Sorge, was some_length sein sollte. Wenn wir nur 100 wählen, sind wir wieder da, wo wir waren.

Wir müssen uns darum kümmern, weil get_command_argument ein Argument mit verzögerter Länge nicht akzeptiert und es der gewünschten Länge zuordnet. Das ist

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

bietet die Antwort "Nein".

Kommend, dann, zu einem Weg, damit umzugehen, schauen wir uns andere (optionale) Argumente zu get_command_argument. Insbesondere gibt es eine length genannt:

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 

Natürlich könnte man ein Wrapper-Unterprogramm erstellen, die einen zuordenbaren latenten Länge Zeichenvariable nehmen taten und taten aller Arbeit.

+0

Ihr Ansatz ist viel besser, irgendwie habe ich dieses Argument vergessen. –

+0

Vielleicht ist es auch erwähnenswert, dass dieser Ansatz auch für 'get_environment_variable' funktioniert. – francescalus

+0

Danke, das ist eine große Hilfe und löst tatsächlich die Frage.Ich habe nur eine kleine Frage, warum ist es notwendig, die ziemlich gewundene 'allocate (character (some_length) :: Argument)' anstelle der einfacheren 'allocate (Argument (some_length))' – Onturenio

1

Ich werde dies für die Vollständigkeit verlassen, kann es für jemanden nützlich sein, aber Francescalus 'Antwort ist viel besser.

Im Grunde, lesen Sie es nur mit einer Standardlänge, überprüfen Sie die STATUS Variable und wenn es nicht passte, versuchen Sie es erneut.

Vom gcc Handbuch:

Wenn das Argument nicht aufgerufen werden kann, ist STATUS eine positive Zahl; Wenn VALUE ein abgeschnittenes Befehlszeilenargument enthält, ist STATUS -1; und ansonsten ist der STATUS Null.

So:

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 
Verwandte Themen