Dynamic allocation of Fortran strings

Dynamic allocation of Fortran strings

Hi,My compiler version is 11.1.051I'am facing difficulties to allocate fortran strings of variable length.I have declared:

character(len=:), allocatable :: str(:)

but I don't know the syntax to allocate the length and size of the str element at the same time.If I declare:

allocate(str(nbLines))

I get the error message #8232, whcih is particularly unclear:
error #8232: If any object being allocated in the ALLOCATE statement has deferred type parameter, either type specification or SOURCE= shall appear. [STR]
Furthermore, I cannot find any explanation of the SOURCE= qualifier from the help.What does this means ?What is the correct syntax ?Thanks

18 帖子 / 0 全新
最新文章
如需更全面地了解编译器优化,请参阅优化注意事项

The syntax is

character(len=:),allocatable :: str(:)
integer :: clen, nbLines
...
allocate(character(clen) :: str(nbLines))
...

Thanks!

I will try this ASAP.

Thanks again, it works perfectly.Now I have a side question regarding allocatable fortran strings.Is it possible to allocate a single fortran string of deferred length without using an array of one element?i.e. declaring :

character(len=:), allocatable :: string
.../...
read(*,*) lg
allocate(character(len=lg) :: string)
.../...

This seems to work (i.e. no compilation or runtime errors), but the debugger reports an error when looking at the allocated object (Substring arguments out of bounds).Is this use correct ?

Yes, you can do this with a scalar character variable. The debugger support of this Fortran 2003 feature is a bit behind. Note that you can simply assign to "string" to set its value, but you can't get the implicit reallocation with a READ. (I mention this because it is a common question.)

Steve

Thanks, steve for your quick answer; however I don't understand what do you mean by :

Note that you can simply assign to "string" to set its value, but you can't get the implicit reallocation with a READ. (I mention this because it is a common question.

You can do

character(len=:), allocatable :: str
integer :: lstr
...
read(*,*)lstr
allocate(character(len=lstr) :: str)
..

but not

character(len=:), allocatable :: str
..
< str not allocated>
..
read(*,*)str
..

To be specific, you can use "str" in a READ, but it must already be allocated to the desired size. The READ will not allocate the variable.

Steve

Of course.

Thank you again steve.

Hi all,

I recently wondered whether I have to deallocate the allocated strings?

program character_array
    implicit none
    ! Variables
    character(len=:), allocatable :: str
    integer,parameter             :: lstr=20
    !
    ! Body of character_array
    write(*,*) '======= character test ========='
    !
    allocate(character(len=lstr) :: str)
    str = 'dummydummydummydummy'
    if(allocated(str)) deallocate(str)
       
end program character_array

Is that the correct way to handle allocated strings? The code above works without complains on Windows with ifort and Linus with ifort as well as gcc (4.6.3).

Best regards,

Johannes

The code you have is fine, but both the ALLOCATE and DEALLOCATE are optional in this context. The ALLOCATE isn't required because str will automatically get allocated to the length of the right-hand-side on an assignment and in fact will get reallocated on the assignment here no matter what length you specified in the ALLOCATE. The DEALLOCATE isn't required because, as a local, non-SAVE variable, it will be automatically deallocated on exit (or procedure end if in a procedure.)

There isn't anything wrong with your code, but it does more than it needs to.

Steve

>> in fact will get reallocated on the assignment here no matter what length you specified in the ALLOCATE

Even if the output side (lhs) is .ge. number of characters of the input side (rhs)?

I can see performance issues if the = operation (on allocatable strings/other) always performs a deallocation/allocation.

Jim Dempsey

www.quickthreadprogramming.com

Yes, even in such cases. Yes, there is some performance overhead to this, but the behavior is required by the standard and it's generally what people want when using this feature. The deallocate/reallocate isn't very complicated in this context, so I wouldn't worry about it a lot. (And, if you're wondering if /assume:realloc_lhs is needed to get this behavior, the answer is no. Keep in mind that we are discussing deferred-length allocatable character variables - other types of variables may behave differently.)

Steve

My experience of this is that

str = 'dummydummydummydummy'

without allocate only works in debug code. In release I usually get a crash so to be safe I always use

allocate(str, source='dummydummydummydummy')

Simon

It should work everywhere. If you have a test case that shows it doesn't, please show it to us. I have used this feature a lot.

Steve

It is a hard one to track down but looking at my change logs I see that the last time I had to change the code for this problem was 24th September. I tried winding back the code to that date but could not reproduce the bug.

It is possible that this problem is due to the fact that we are currently using the 12.1.0.233 compiler which is a bit old now. We are evaluating the 14.0.0.103 at the moment so the problem may go away once we move to that.

Given that there was a direct question about this I just thought I let people know my experience. If I can isolate an instance of the problem in a small program I'll let you know or log it as a bug with Premier Support.

Simon

Dear all,

thank your very much for your answers.

I extended the example of mine a little bit and played around with it. As Steve said, defining str in a module with the save attribute requires a deallocation. The character allocatables behave like 'normal-non-F2003' allocatables in this case. My local character t0end is deallocated automatically at the end of the subroutine.

I could not reproduce the behavior Simon describes. If I comment line 14 in sub_dummy.f90, the program works as well as before in Debug and Release mode (ifort 12.1 update 12). The deallocation is in both cases mandatory.

!line 14
allocate(character(len=lstr) :: str)

Kind regards,

Johannes

附件: 

附件尺寸
下载 character-array.zip6.17 KB

Hi,

Just comment on ALLOCATE issue: "The code you have is fine, but both the ALLOCATE and DEALLOCATE are optional in this context." 

This is also valid to apply for array string variable. For eg.

Character(:),dimension(:),allocatable::StrArray
Character(:),allocatable::StrScalar

StrScalar='Something to fill the two elements....';  ! ------------------------ is OK!

StrArray=['1. This is the first element','2. This is the second element.'];  ! ------------------------ is also OK or alternatively...

allocate(character(len(='Something to fill the two elements....'))::StrArray(2)) ! or alternatively...

allocate(StrArray,source=['1. This is the first element','2. This is the second element.']);

Have a nice weekend, 

Kong

登陆并发表评论。