Вопрос

I can't tell what is wrong with this free form Fortran program. It does not correctly handle its command line arguments.

It works if I use a static array for the command line argument instead of an allocatable array.

Also, is this a good first Fortran program? Is this the type of problem for which Fortran would be useful? I already know C, C++, and a little bit of 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
Это было полезно?

Решение

This line

character, allocatable :: argumen(:)

declares an allocatable array of characters. So the statement

allocate(argumen(size))

makes argumen an array of 20 single-character elements. That's not the usual way of dealing with strings in Fortran and argumen doesn't match (in type or rank) the requirements for the second argument in the call to get_command_argument.

Instead you should write

character(len=:), allocatable :: argumen

to declare argumen to be a character variable of allocatable length. In some contexts you can simply assign to such a variable, e.g.

argumen = 'this is the argument'

without having to previously allocate it explicitly.

With Intel Fortran v14 the call to get_command_argument compiles without warning but on execution the argument argumen isn't automatically allocated and it remains unassigned. I'm honestly not sure if this behaviour is standard-conforming or not. One approach would be to make two calls to get_command_argument, first to get the size of the argument, then to get the argument; like this

 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

Using the name length for the variable to be assigned the value returned by the optional argument called length is legal but a mite confusing. The deallocate statement ensures that argumen can be allocated again for the next argument.

I'll leave you the exercise of declaring, and using, an allocatable array of allocatable-length characters.

Disclaimer: the next two paragraphs contain material which some may find subjective. I will not be entering into any discussion about these parts of this answer.

Is this a good first Fortran program ? It's better than a lot of what I see here on SO. Personally I prefer the consistent use of the modern /= to .ne., < to .lt (etc), I don't use stop if I can avoid it (I usually can), and I'm sure I could find other nits to pick.

Is this the type of problem for which Fortran would be useful? Fortran is useful for all types of problem, though I admit it can be quite challenging using it to write a web server.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top