2016-02-02 4 views
5

Я хотел бы прочитать в некоторых текстовых строках из командной строки, используемой для запуска программы. Я использую внутреннюю подпрограмму GET_COMMAND_ARGUMENT в программе, которая в основном является что-то вроде:Как получить аргументы командной строки неизвестной длины в Fortran?

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

Проблема здесь в том, что я чувствую, что это немного опасно, чтобы установить максимальную длину строки во время компиляции. Некоторые из аргументов обычно являются файлами со своим путем, поэтому они могут быть очень длинными. Решение с установкой длины статически до 1000 звучит как уродливое обходное решение.

Не существует ли более элегантный способ в Фортране для определения строки, способной содержать цепочку символов, длина которой известна только во время выполнения?

ответ

4

можно использовать так называемые переменный характер отложенной длину. Они не имеют фиксированной постоянной длины, и их использование можно найти в таких вопросах, как a related one about data input.

Однако, даже с отложенным переменной длины используется как (для этого синтаксис)

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

один еще должен беспокоиться о том, что some_length должно быть. Если мы просто выберем 100, мы вернемся туда, где мы были.

Мы должны беспокоиться об этом, потому что get_command_argument не принимает такой аргумент отложенной длины и выделяет его на нужную длину. То есть

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

предлагает ответ «нет».

Приступив к способу справиться с этим, мы рассмотрим другие (необязательные) аргументы get_command_argument. В частности, есть одна называется 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 

Естественно, можно была бы создать подпрограмму обертки, которая делала принять размещаемые отложенные переменную длину символов и сделала всю эту работу.

+0

Ваш подход намного лучше, так или иначе я забыл этот аргумент. –

+0

Возможно, также стоит отметить, что этот подход работает также и для 'get_environment_variable'. – francescalus

+0

Спасибо, это очень помогает и действительно решает вопрос.У меня есть лишь незначительный вопрос: зачем нужен довольно запутанный 'allocate (character (some_length) :: argument) вместо более простого' allocate (argument (some_length)) ' – Onturenio

1

Я оставлю это для полноты, это может быть полезно кому-то, но ответ francescalus намного лучше.

В принципе, просто прочитайте его с некоторой длиной по умолчанию, проверьте переменную STATUS, и если она не подходит, попробуйте еще раз.

Из ССАГПЗ руководства:

Если извлечь аргумент несостоятелен, STATUS положительное число; если VALUE содержит усеченный аргумент командной строки, STATUS - -1; и , иначе STATUS равен нулю.

Итак:

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