2016-02-02 12 views
5

Chciałbym przeczytać w niektórych ciągach tekstowych z wiersza polecenia używanego do uruchomienia programu. Używam wewnętrzny podprogram GET_COMMAND_ARGUMENT w programie, który w zasadzie jest coś takiego:Jak zdobyć argumenty wiersza poleceń o nieznanej długości w Fortranie?

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

chodzi tu o to, że czuję, że to trochę niebezpieczne, aby ustawić maksymalną długość łańcucha w czasie kompilacji. Niektóre z argumentów są zwykle plikami z ich ścieżką, więc mogą być bardzo długie. Rozwiązanie polegające na ustawieniu długości statycznie na 1000 brzmi jak brzydkie obejście.

Nie ma bardziej eleganckiego sposobu w Fortranie, aby zdefiniować ciąg znaków, który może zawierać łańcuch znaków, którego długość jest znana tylko w czasie wykonywania?

Odpowiedz

4

Jest możliwe użycie tak zwanych zmiennych znakowych odroczone długości. Nie mają stałej stałej długości, a ich użycie można znaleźć w pytaniach takich jak a related one about data input.

Jednakże, nawet przy zmiennej długości odroczony używany jak (bo to jest składnia)

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

jeden wciąż musi martwić się o to, co some_length powinno być. Jeśli wybierzesz 100, wrócimy tam, gdzie byliśmy.

Musimy się tym martwić, ponieważ get_command_argument nie przyjmuje takiego argumentu o odroczonej długości i nie przydziela go do pożądanej długości. To jest

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

oferuje odpowiedź "nie".

Wracając do sposobu rozwiązania tego problemu, przyjrzymy się innym (opcjonalnym) argumentom pod numerem get_command_argument. W szczególności, nie jest jeden o nazwie 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 

Naturalnie, można utworzyć otoki podprogram który wziął się allocatable zmienną długość znaków odroczony i uczynił wszystko, pracę.

+0

Twoje podejście jest o wiele lepsze, jakoś zapomniałem tego argumentu. –

+0

Być może warto również zauważyć, że to podejście działa również dla 'get_environment_variable'. – francescalus

+0

Dzięki, to bardzo pomaga i rzeczywiście rozwiązuje pytanie.Mam tylko drobne pytanie, dlaczego konieczne jest raczej zawiłe "przydzielić (argument (część długości) :: zamiast prostszego" przydzielić (argument (trochę długości)) " – Onturenio

1

Zostawię to dla kompletności, może być użyteczne dla kogoś, ale odpowiedź francescalus jest znacznie lepsza.

Zasadniczo, po prostu przeczytaj z pewną domyślną długością, sprawdź zmienną STATUS, a jeśli nie pasuje, spróbuj ponownie.

Z gcc instrukcji:

Jeśli pobieranie nie powiedzie się argumentem, STATUS jest liczbą dodatnią; jeśli VALUE zawiera obcięty argument wiersza poleceń, STATUS to -1; i inaczej STATUS wynosi zero.

Więc:

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 
Powiązane problemy