Marty Farce
Marty Farce

Reputation: 115

How to make a string[] array in Fortran

I first make a dynamic character array

! whatever I assign to line will be its length
character(len=:), allocatable :: line

then I want to make this a dynamic array of these dynamic character arrays, so refactoring to this:

type(character(len=:)), allocatable, dimension(:) :: lines

allocate(lines(21))

yields this error;

Allocate-object at (1) with a deferred type parameter requires either a type-spec or SOURCE tag or a MOLD tag

however, if I allocate the array on variable declaration step like so:

type(character(len=:)), allocatable, dimension(21), target :: lines

I get this error:

Allocatable array 'lines' at (1) must have a deferred shape or assumed rank

First off, is this even possible? as languages like python have dynamic string arrays built in and you don't have to think about it, but in fortran things are a little more complicated to get the right kind of string you need

Secondly, is this a good idea? or is there a fortran practice that I am unaware of to get 21 individual character arrays that have an unknown length. Giving these characters a fixed length will work for my problem like so:

type(character(len=256)), allocatable, dimension(:), target :: lines

allocate(lines(21))

But knowing that I can only have max 256 in my character bothers me for when I get something larger than 256, what happens then? do I lose data?

Thirdly, how can I achieve this goal of a string[] in fortran? I've exhausted all ideas.

P.S. I am using gfortran version 9.4

Edit:

per the solution by @veryreverie, the code for string[] (jagged array) in fortran looks like this:

type :: stringType
   character(len=:), allocatable :: string
end type

type(stringType), allocatable, dimension(:) :: lines

allocate(lines(21))
do i = 1, 21
   lines(i)%string = doSomeStringOperation()
end do

Upvotes: 2

Views: 1177

Answers (1)

francescalus
francescalus

Reputation: 32366

Your allocatable object

type(character(len=:)), allocatable, dimension(:) :: lines

has both a deferred type (length) parameter (len=:) and deferred shape (dimension(:)). When allocating this object you must give values to both of these.

The allocation statement

allocate(lines(21))

provides the array shape, but not the type parameter.

To provide the type parameter you must use the "type-spec" or "source"/"mold" of the error message:

allocate (character(len=27) :: lines(21))

or

allocate (lines(21), source="                           ")

It's possible to have a fixed length in an allocatable character variable, but the shape of an array must always be deferred (or its rank assumed).

As you'll see in other questions, the lengths of the elements of such an array must all be the same. If you want elements of different lengths, you cannot use an array and should use a derived type with character component instead. (Much as with "jagged" arrays.)

Upvotes: 4

Related Questions