- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is the code:
program main implicit none character(:), allocatable :: i write(*,*)["1","1"//"2"] i="2" write(*,*)["1","1"//i] end program
I expect this two write will give the same results. But the first one gives ["1 ","12"] while the second one truncate "1"//i to "1". I know this may due to the fact that at compile time compiler can not estimate the length of "1"//i so it make the length with the longest length it can measure (which is one in this case). I think this is quite unexpected and compiler should warn about it or just raise an error.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try this:
character(len=:), allocatable :: i write(*,*) [ character(len=2) :: "1","1"//"2" ] i="Hello World!" write(*,*)[ character(len=len_trim(i)+1) :: "1","1"//i ]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for response!
What I wonder is that is it ok to let the code I mentioned above compiled without any warning/error?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You might submit this as a feature request for gfortran compatibility:
$ gfortran -Wall zy.f90
zy.f90:4:43:
write(*,*)["1","1"//"2"]
1
Error: Different CHARACTER lengths (1/2) in array constructor at (1)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
But gfortran doesn't raise error for second write statement neither. By the way, I like what ifort does for the first write statement.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The standard says that all "ac-values" in a character array constructor have the same length. You can specify what that length is to be with a CHARACTER(n):: prefix in the constructor, as FortranFan shows. As an extension, when all the values are compile-time constants, Intel Fortran will use the length of the longest value. If not all the values are constants, then it picks the length of the first value. Either usage is nonstandard.
If you ask ifort for standards checking, it will complain:
t.f90(4): warning #8208: If type specification is omitted, each ac-value expression in the array constructor of type CHARACTER must have the same length type parameters. ['1']
write(*,*)["1","1"//"2"]
-------------------^
Since we have an extension that defines an interpretation, it isn't an error for us in the way gfortran treats it.
The second case is not detectable at compile-time as the variable could be length zero.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
While with standards checking enabled, the second case is still without warning. My suggestion is that it should also warn in second case as "i" could be any length other than zero!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
But it could also be zero. We don't give warnings or errors unless we can prove that there's a problem. A compiler is required to have the ability to diagnose syntax that does not conform to numbered syntax rules or constraints, but the second example violates neither.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I see. Thanks again!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Something related:
program character_len_array implicit none integer :: i character(len=:), dimension(:), allocatable :: ca ca = ['a','bb'] ! works print *,ca ! works !dir$ if (.false.) do i=1,ubound(ca) ! error #6512: A scalar-valued expression is required in this context. print *,ca(i) end do !dir$ else do i=1,2 print *,ca(i) end do !dir$ endif end program character_len_array -------------- a bb a bb
Steve,
print *,ca(i), size(ca(i)) ! produces error
however
print *,ca(i), len(ca(i))
produces
a bb a 2 bb 2
So the [] array constructor worked, but not as desired (different lengths), I know that this behavior is following Fortran specifications.
This one is interesting:
program character_len_array implicit none integer :: i character(len=:), dimension(:), allocatable :: ca, ca2 character(len=:), allocatable :: ca2mold ca = ['a','bb'] ! works print *,ca ! works !dir$ if (.false.) do i=1,ubound(ca) ! error #6512: A scalar-valued expression is required in this context. print *,ca(i) end do !dir$ else do i=1,2 print *,ca(i), len(ca(i)) end do !dir$ endif allocate(ca(2),mold=ca2mold) ca2(1) = 'aaaa' ca2(2) = 'bbbbbbbb' do i=1,2 print *,ca2(i), len(ca2(i)) end do end program character_len_array ------------------- a bb a 2 bb 2 forrtl: severe (151): allocatable array is already allocated Image PC Routine Line Source libifcoremdd.dll 0F6FDA35 Unknown Unknown Unknown character_len_arr 01101625 _MAIN__ 31 character_len_array. f90 character_len_arr 01101B7F Unknown Unknown Unknown character_len_arr 011044E9 Unknown Unknown Unknown character_len_arr 0110462D Unknown Unknown Unknown kernel32.dll 76E5338A Unknown Unknown Unknown ntdll.dll 77389902 Unknown Unknown Unknown ntdll.dll 773898D5 Unknown Unknown Unknown
Compiled ok, aborted during runtime
The intention of the ca2 was to avoid using a user defined type, containing a pointer to a character(len=:) :: p, then using ca2(i)%p
---
gripe: can someone get the webmaster to NOT auto upcase I (lower case i). It is a pain in the ass to work around the upcase when writing code examples in the body of the post. Everyone can understand when i use a lower case I for me. Disambiguating I from l is problematic (lower case I from lower case L).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
i don't think the web site is uppercasing i. maybe your web browser is doing it.
Jim, in your first example, ['a','bb'] works because of our extension I described previously. As your later code shows, we extend 'a' to 'a '.
The use of UBOUND(ca) gets an error because this has an array result. You want UBOUND(ca,DIM=1) instead.
What do you think is a problem with that last example? When you get to the allocate, ca has already been allocated at line 6.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Me bad, I should have allocated ca2, not ca
... allocate(ca2(2),mold=ca2mold) ca2(1) = 'aaaa' ca2(2) = 'bbbbbbbb' do i=1,2 print *,ca2(i), len(ca2(i)) end do ---- 0 0
It didn't produce what I wanted (I guess I got what I deserved).
I was expecting the reallocate lhs to redefine the len=: of each element of the array ca2. However, I guess the specification requires all elements of the (character) array to be of equal length, iow the LEN property is that of the array and not that of the (each) element.
I think this is what Zoudong was looking for. He (she?) will have to accept using LEN= at worst case requirement, or use an array of pointers with the extra coding effort. Use of FPP preprocessor with appropriately #defined macros may eliminate the extra coding effort.
program character_len_array implicit none integer :: i type character_pointer character(len=:), allocatable :: cp end type character_pointer type(character_pointer), dimension(:), allocatable :: ca ca = [ca, character_pointer("a")] do i=1,size(ca) print *,ca(i)%cp,len(ca(i)%cp) end do ca = [ca, character_pointer("bb")] do i=1,size(ca) print *,ca(i)%cp,len(ca(i)%cp) end do #define ca(n) CA(n)%cp do i=1,size(CA) ! note case difference print *,ca(i),len(ca(i)) end do end program character_len_array -------------- a 1 a 1 bb 2 a 1 bb 2
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Better example:
program character_len_array implicit none integer :: i type character_pointer character(len=:), allocatable :: cp end type character_pointer type(character_pointer), dimension(:), allocatable :: ca ca = [character_pointer("Short message")] ca = [ca, character_pointer("Longer message than the First message")] #define ca(n) CA(n)%cp do i=1,size(CA) ! note case difference print *,ca(i),len(ca(i)) end do end program character_len_array -------------- Short message 13 Longer message than the First message 37
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I forgot to mention, the use of FPP macros will preclude you from using the macro name in the debug session. In the above example, the two are intuitively interchangeable. More complex macros would be a bit more cumbersome for debugging.
(character_pointer is a misnomer, character_message, might be better)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
Me bad, I should have allocated ca2, not ca
... allocate(ca2(2),mold=ca2mold) ca2(1) = 'aaaa' ca2(2) = 'bbbbbbbb' do i=1,2 print *,ca2(i), len(ca2(i)) end do ---- 0 0It didn't produce what I wanted (I guess I got what I deserved).
You allocate ca with a shape of [2] and specify ca2mold for mold=. Since ca2mold is unallocated, the program is immediately nonconforming:
F2008 6.7.1.2 - emphasis mine
5 If source-expr is a pointer, it shall be associated with a target. If source-expr is allocatable, it shall be allocated.
What apparently happens is that zero is used as the "length type parameter" and therefore the assignments are ignored.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So there is no practical way to do what I did in #13 without the use of the UDT (and corresponding requirement of %memberVariable).
It is interesting (to me) that character_pointer("SomeText") implicitly converts the argument where
characterVar = ca(i)
does not. No symmetry. A user defined copy operator would be required. This would not satisfy LEN(ca(i)), with no macro assist.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran does not have the concept of an array where each element has different type parameters (length is a type parameter). Using a type is the only way to do this. Similarly, Fortran does not have the concept of an array of pointers - again you need a user-defined type.
character_pointer("SomeText") is a structure constructor. With a component that is allocatable, you're effectively doing an ALLOCATE with SOURCE= the value and this will allocate to the length of the value.
I'm not sure what you're asking about "characterVar" since that isn't in any of the examples so far. If that's ALLOCATABLE, CHARACTER(:), it will get reallocated on assignment to the length of the value being assigned, but from the examples here, ca is a derived type so unless you have user-defined assignment for that combination, such an assignment is not allowed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
So there is no practical way to do what I did in #13 without the use of the UDT (and corresponding requirement of %memberVariable).
It is interesting (to me) that character_pointer("SomeText") implicitly converts the argument where
characterVar = ca(i)
does not. No symmetry. A user defined copy operator would be required. This would not satisfy LEN(ca(i)), with no macro assist.
Jim Dempsey
You can write a function that has a dummy argument of the derived type `character_pointer` (or whatever you want to call it) and stick it behind a generic interface named LEN. The LEN intrinsic will still be available for real CHARACTER arguments.
You can write UDDTIO procedures for that derived type.
In combination with things like defined assignment and other defined operations, the requirement for %memberVariable becomes pretty nominal.
(Several examples of "string" types with this sort of stuff are already publicly available, so, if they suit, the amount of new code writing that needs to be done may be very small.)
I would not use the preprocessor for this sort of stuff.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks IanH.
Do you have a link to your favorite string types?
I too would prefer not to use the preprocessor due to portability and debugging issues.
BTW, I think it was an unfortunate naming to use UDDTIO since the name seems to imply related to I/O (READ/WRITE). The naming does not infer the section can be used for other purposes (the document should include some clear-cut examples).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Um, UDDTIO is just for I/O - it has no other purposes. Ian was just saying that you can treat these "variable string types" as normal variables in READ/WRITE with a suitable UDDTIO procedure.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
Thanks IanH.
Do you have a link to your favorite string types? ..
Jim,
Just in case IanH hesitates to recommend his own work:-)), see this:
You may also to want to look at https://groups.google.com/forum/#!topic/comp.lang.fortran/qONziG36nFs
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page