2013-11-21 4 views
3

Я не могу сказать, что не так в этой бесплатной форме программы Fortran. Он неправильно обрабатывает аргументы командной строки.Что не так с этой программой Fortran?

Он работает, если я использую статический массив для аргумента командной строки вместо массива allocatable.

Кроме того, это хорошая первая программа Fortran? Это тип проблемы, для которой Fortran был бы полезен? Я уже знаю, C, C++, и немного D.

module fibonacci 
    use ISO_FORTRAN_ENV 
    implicit none 
contains 
    subroutine output_fibonacci(ordinal) 
    ! Declare variables 
    integer, parameter :: LongInt = selected_int_kind (38) 
    integer, intent(in) :: ordinal 
    integer :: count 
    ! integer (kind=LongInt) :: count, compare=2 
    integer (kind=LongInt), dimension(2,2) :: matrix, initial 
    matrix=reshape((/ 1, 1, 1, 0 /), shape(matrix)) 
    initial=reshape((/ 1, 0, 0, 1 /), shape(initial)) 
    count = ordinal 
    ! Do actual computations 
    do while (count > 0) 
     ! If the exponent is odd, then the output matrix 
     ! should be multiplied by the current base 
     if (mod(count,2) == 1) then 
      initial = matmul(matrix, initial) 
     end if 
     ! This is the squaring step 
     matrix = matmul(matrix, matrix) 
     count = count/2 
    end do 
    write (*,*) initial(1,2) 
    end subroutine output_fibonacci 
end module fibonacci 
program main 
    use, intrinsic :: ISO_FORTRAN_ENV 
    use fibonacci 
    implicit none 
    ! The maximum allowed input to the program 
    integer :: max=200, i, size=20 
    character, allocatable :: argumen(:) 
    integer :: error, length, input 
    allocate(argumen(size)) 

    ! write(*,*) argcount 
    do i=1, command_argument_count() 
    call get_command_argument(i, argumen, length, error) 
    read(argumen,*,iostat=error) input 
    ! write(*,*) argument 
    ! write (*,*) input 
    if (error .ne. 0) then 
     write(ERROR_UNIT,'(I36.1,A)') input, "is not an integer" 
     stop (1) 
    else if (input > max) then 
     write(ERROR_UNIT,'(A,I36.1,A)') "Input ", input, " is too large" 
     stop (1) 
    end if 
    call output_fibonacci(input) 
    end do 
end program 

ответ

8

Эта линия

character, allocatable :: argumen(:) 

объявляет размещаемый массив символов. Так что утверждение

allocate(argumen(size)) 

делает argumen массив из 20 элементов односимвольных. Это не обычный способ работы со строками в Fortran, а argumen не соответствует (в типе или ранге) требованиям для второго аргумента при вызове get_command_argument.

Вместо этого вы должны написать

character(len=:), allocatable :: argumen 

объявить argumen быть изменчивый характер распределяемой длины. В некоторых контекстах вы можете просто назначить такую ​​переменную, например.

argumen = 'this is the argument' 

без предварительного выделения его явно.

С Intel Fortran v14 вызов get_command_argument компилируется без предупреждения, но при выполнении аргумент argumen не назначается автоматически и остается неназначенным. Я честно не уверен, соответствует ли это поведение стандарту или нет. Один из подходов состоял бы в том, чтобы сделать два вызова get_command_argument, сначала получить размер аргумента, затем получить аргумент; как это

do i=1, command_argument_count() 
    call get_command_argument(i, length=length, status=error) 
    allocate(character(length)::argumen) 
    call get_command_argument(i, argumen, status=error) 
    ! do stuff with argument 
    deallocate(argumen) 
    end do 

Используя имя length для переменной присваивается значение, возвращаемое дополнительным аргументом называется length является законным, но клеща в заблуждение. Оператор deallocate гарантирует, что argumen может быть выделен снова для следующего аргумента.

Я оставлю вам упражнение объявления и использования выделенного массива символов с разделительной длиной.

Отказ от ответственности: следующие два абзаца содержат материал, который некоторые могут найти субъективным. Я не буду вступать в какие-либо обсуждения этих частей этого ответа.

Является ли это первой первой программой Fortran? Это лучше, чем то, что я вижу здесь, на SO. Лично я предпочитаю последовательное использование современных /= к .ne., < к .lt (и т.д.), я не использую stop, если я могу избежать этого (я обычно могу), и я уверен, что я мог бы найти другие гнида в выбирать.

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

Смежные вопросы