I'd like to read in some text strings from the command line used to run a program. I'm using the internal subroutine GET_COMMAND_ARGUMENT
in a program that basically is something like:
program test
character(len=100) :: argument
call GET_COMMAND_ARGUMENT(1,argument)
print*, argument
end program test
The issue here is that I feel it's a bit dangerous to set the maximum length of the string at compilation time. Some of the arguments are typically files with their path, so they might be very long. A solution involving setting the length statically to 1000 sounds like an ugly workaround.
Isn't there a more elegant way in Fortran to define a string able to contain a chain of characters whose length is only known at run time?
It is possible to use what are called deferred-length character variables. These are not of a fixed constant length and their use can be found in questions such as a related one about data input.
However, even with a deferred length variable used like (for this is the syntax)
character(len=:), allocatable :: argument
allocate(character(some_length) :: argument) ! For integer some_length
call GET_COMMAND_ARGUMENT(1,argument)
print*, argument
end
one still has to worry about what some_length
should be. If we just choose 100, we're back to where we were.
We have to worry about this because get_command_argument
as is currently widely implemented doesn't take such a deferred length argument and allocate it to the desired length. That is
character(len=:), allocatable :: argument
call GET_COMMAND_ARGUMENT(1,argument) ! Will argument be allocated in the subroutine?
print*, argument
end
offers the answer "no".1
Coming, then, to a way to handle this, we look at other (optional) arguments to get_command_argument
. In particular, there is one called 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
Naturally, one could create a wrapper subroutine which did take an allocatable deferred length character variable and did all that work.
1 Fortran 2023 changes the behaviour of intrinsic procedures which take character variables. get_command_argument
, along with many others, in this language revision does now allocate such a deferred-length character. Where the answer was "no" before Fortran 2023 is now "yes". Practically, though, we'll be writing portable Fortran code assuming the answer is "no" for many years yet.