How to get command line arguments of unknown length in Fortran?

I would like to read in some text lines from the command line used to run the program. I am using the internal routine GET_COMMAND_ARGUMENT in a program that is basically something like:

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

The problem here is that it is a little dangerous for me to set the maximum line length at compile time. Some of the arguments are usually files with their own path, so they can be very long. The solution with setting the length statically to 1000 sounds like an ugly workaround.

Is there a more elegant way in Fortran to define a string that can contain a string of characters whose length is known only at run time?

+5
source share
2 answers

You can use so-called deferred character variables. They do not have a fixed constant length, and their use can be found in issues such as data entry .

However, even with a variable deferred length used as (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 

still need to worry about what some_length should be. If we just choose 100, we will go back to where we were.

We need to worry about this because get_command_argument does not accept such a deferred length argument and allocates it to the desired length. it

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

offers the answer no.

Now, to handle this, we will look at other (optional) arguments for 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, you can create a wrapper routine that takes a portable variable of length of deferred length and it all worked.

+4
source

I will leave it for completeness, it may be useful to someone, but the francescalus answer is much better.

Basically, just read it with some default length, check the STATUS variable, and if it doesn't fit, try again.

From the gcc manual:

If the argument search failed, STATUS is a positive number; if VALUE contains a truncated command line argument, STATUS is -1; otherwise STATUS is zero.

So:

 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 
+1
source

Source: https://habr.com/ru/post/1242090/


All Articles