Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fortran: Initialize character string with unknown length in main program

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.

like image 546
Felix Avatar asked Sep 09 '15 15:09

Felix


People also ask

How do you find the length of a string in Fortran?

len will give you the length of the string including trailing blanks. If you want the length excluding trailing blanks, then use len_trim .


1 Answers

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
like image 171
francescalus Avatar answered Sep 29 '22 22:09

francescalus