What is wrong with this Fortran program?
command-line-arguments, fortran, fortran2003, fortran90
Solution
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.
Problem
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 ```