How to get/query the defined length of a character-type variable

With reference to the following code:

  character(len=128) :: arg
  character(len=128), dimension(:), allocatable :: args

  arg_counter = command_argument_count()
  allocate(args(arg_counter))

  do i = 1, arg_counter
    call get_command_argument(i, args(i), arg_length)
    if (arg_length > 128) then
      ...
    end if
  end do
  • I have seen that character(len=n), with integer(2) :: n = 128 earlier defined, is not accepted. In addition, a statement arg_length > 128 is used. Is there any workaround to avoid writing 128 three times?
  • Is there a way to get/query the character type len property of args variable so as I can simply write: arg_length > func(args)(= 128) ?
    Tia

You have declared args as an array of characters. All elements in that array will have the same length so assuming that you know the array has been allocated you can check len(args(1)).

Often one does not want all strings to be of the same length. I think you might benefit from using a type along these lines:

type :: string_t
    character(len=:), allocatable :: chars
end type

and

type(string_t), allocatable :: args(:)

There’s also numerous libraries which implement variable length string types like this with various utility functions. See e.g. Fortran stdlib: GitHub - fortran-lang/stdlib: Fortran Standard Library

1 Like

So, we have arg_length > len(args(1)). @plevold Tal!

To read an command line argument in a deferred length character you can first query its length, than allocate and finally retrieve the value. This is for example used in a helper routine in test-drive:

Storing into a stdlib string_type or similar allows you to also have them as array without having to worry about padding.

2 Likes

The other comments about using allocatable strings is probably the best solution to your problem. However, to answer your original question, the following will eleminate typing the 128 magic number multiple times:

  integer, parameter :: lmax = 128
  character(len=lmax) :: arg
  character(len=lmax), dimension(:), allocatable :: args

  arg_counter = command_argument_count()
  allocate(args(arg_counter))

  do i = 1, arg_counter
    call get_command_argument(i, args(i), arg_length)
    if (arg_length > lmax) then
      ...
    end if
  end do

You are free to use any parameter name, of course, there are no reserved keywords in fortran. In these declarations, lmax must be a parameter (known at compile time), not a variable. In other cases, e.g. with automatic variables, then a variable length, say a dummy argument or a module variable, would also be allowed. If you decide later to change the max length to, say 256, then you just change that one line of code.

1 Like

Moreover, status argument would also be used instead of arg_length > lmax so that

  integer, parameter :: lmax = 128
  character(len=lmax) :: arg
  character(len=lmax), dimension(:), allocatable :: args

  arg_counter = command_argument_count()
  allocate(args(arg_counter))

  do i = 1, arg_counter
    call get_command_argument(i, args(i), arg_length, status)
    if (status == -1) then
      ...
    end if
  end do