6

I have a character string I would like to initialize with intent(out) data from a subroutine call. I kind of looks like that:

character(*) :: path
call get_path(path)

The compiler tells me:

Error: Entity with assumed character length at (1) must be a dummy argument or a PARAMETER

The construct works just fine in a subroutine but fails in the main program. Is it possible to initialize the path variable without knowing its length?

EDIT: Stuff I already tried but failed.

character(99) :: path_temp
character(:), allocatable :: path
call get_path(path_temp)
allocate(path(len(trim(path_temp))))

Error: Shape specification for allocatable scalar at (1)

I don't get why the compiler thinks path is a scalar.


A function that returns a character with assumed length apparently is illegal.

character(*) function get_path ()
    get_path         =     '/path/to/folder/'
end function get_path

Error: Character-valued module procedure 'get_path' at (1) must not be assumed length


What works but gives me a headache because I find it very bad style is to give path an insane length and trim it every time it's used. I think my compiler is having trouble with allocatable character strings because it isn't quite up to date (mpif90). Not sure if it supports them.

6
  • 2
    This possibly isn't quite a duplicate of stackoverflow.com/q/25051108, but please read it and see if it answers your question. Commented Sep 9, 2015 at 15:51
  • 2
    You have the wrong idea about unknown length. It does not represent "I don't care how long", so much as "length not specified here". But the length does have to be specified somewhere, as the program must provide the appropriate amount of storage for it. You could possibly solve your problem by making get_path() a function returning the path as a character(len=*), instead of trying to accept it as an argument. Commented Sep 9, 2015 at 15:51
  • 2
    Can you use an allocatable string? stackoverflow.com/questions/20908053/… Commented Sep 9, 2015 at 15:55
  • 1
    Does path have an expected maximum length? Depending on the situation, I'll temporarily store a string of unknown length into a long, fixed-length variable, then use trim() and adjustl() to strip whitespace before storing it in a variable-length allocatable character variable. Commented Sep 9, 2015 at 16:41
  • 1
    The compiler thinks path is a scalar because it is. It's a scalar character of deferred length, not a character array. To allocate such a scalar with length x, say, do allocate (character(x) :: path), or just do path=trim(path_temp) and have the deferred length path allocated on intrinsic assignment. Commented Sep 9, 2015 at 19:35

1 Answer 1

7

Many of the points are covered in other answers linked by comments, such as what "assumed length" requires and how to allocate the scalar deferred length character variable.

I'll point out two things, before coming to an particular answer.

Intrinsic assignment to a deferred length allocatable scalar character variable results in (if required) allocation of that variable to the length of the expression. That is

character(99) :: path_temp
character(:), allocatable :: path

call get_path(path_temp)
allocate(character(len(trim(path_temp))) :: path)  ! Note the correct form
path = TRIM(path_temp)  ! Or path(:)=path_temp

can be replaced by

character(99) :: path_temp
character(:), allocatable :: path

call get_path(path_temp)
path = TRIM(path_temp)

The other thing to note is quite pedantic, but using the terminology incorrectly may hinder searching. Initialization in Fortran means something specific which isn't applicable here.

You say that a function with an assumed length character result is apparently illegal, based on the compiler error message

Error: Character-valued module procedure 'get_path' at (1) must not be assumed length

That isn't entirely true: character function results can (currently - it's an obsolescent feature of modern Fortran) be of assumed length in some circumstances. They must, though, be external functions. See that the compiler complains about a module procedure (which then isn't external).

That said, having an assumed length character result doesn't help you. The length of the result still has to be assumed from something, and that something isn't in the function body, but a declaration that defines the external function in a scope.

Something like

implicit none

character(99) get_path    ! The length of the get_path result is assumed from here
character(:), allocatable :: path

path = TRIM(get_path())
...

As you seem to have complete control over the subroutine get_path, there's the final answer-worthy comment to make. You could directly have the argument allocatable.

subroutine get_path(path)
  character(:), allocatable, intent(out) :: path
  path = '/path/to/folder/'   ! Allocation through intrinsic assignment
  path = TRIM(path)           ! In general, if it's likely to have trailing blanks
end subroutine
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.