From: Jovan Cormac on
I have a subroutine that accepts an array of variable-length strings of
variable size (assumed-shape array) and is to output all of those strings:


SUBROUTINE routine1(strings)
IMPLICIT NONE

CHARACTER (LEN = *), INTENT(IN) :: strings(:)
INTEGER :: i

WRITE(*,*) (strings(i), i = 1, SIZE(strings))

RETURN
END SUBROUTINE routine1


If I call this subroutine using e.g.

CALL routine1( (/ 'Hello', ' ', 'World!' /) )

I get the following output:

Hello World!


As it turns out, the array "strings" is not actualy an array of
variable-length strings as I want it to be, but rather an array of
*fixed-length strings the length of the longest string passed*.

Therefore, the single character ' ' gets inflated to match the length of
the other two strings.

The obvious hack to go around this is to TRIM the strings before
outputting them:


WRITE(*,*) (TRIM(strings(i)), i = 1, SIZE(strings))


However, in the above case, this of course results in:

HelloWorld!

being written, because the whitespace character gets trimmed down to
nothing.



More promising looks the idea of getting the length of each passed
string and truncating before outputting:


WRITE(*,*) (strings(i)(1:LEN(strings(i)), i = 1, SIZE(strings))


However, as mentioned above, the strings all actually have the same
internal length!



Is there any way to determine the "real" length of the strings passed
through the array? If not, is there maybe another solution to my problem?

Thanks in advance.


--
-- jovan
From: mecej4 on
Jovan Cormac wrote:

> I have a subroutine that accepts an array of variable-length strings of
> variable size (assumed-shape array) and is to output all of those strings:
>
>
> SUBROUTINE routine1(strings)
> IMPLICIT NONE
>
> CHARACTER (LEN = *), INTENT(IN) :: strings(:)
> INTEGER :: i
>
> WRITE(*,*) (strings(i), i = 1, SIZE(strings))
>
> RETURN
> END SUBROUTINE routine1
>
>
> If I call this subroutine using e.g.
>
> CALL routine1( (/ 'Hello', ' ', 'World!' /) )
I put 'routine1' into the calling program source as a CONTAINed subroutine,
and GFortran says:

CALL routine1( (/ 'Hello', ' ', 'World!' /) )
1
Error: Different CHARACTER lengths (5/1) in array constructor at (1)
>
> I get the following output:
>
> Hello World!
>
>
> As it turns out, the array "strings" is not actualy an array of
> variable-length strings as I want it to be, but rather an array of
> *fixed-length strings the length of the longest string passed*.
>
> Therefore, the single character ' ' gets inflated to match the length of
> the other two strings.
>
> The obvious hack to go around this is to TRIM the strings before
> outputting them:
>
>
> WRITE(*,*) (TRIM(strings(i)), i = 1, SIZE(strings))
>
>
> However, in the above case, this of course results in:
>
> HelloWorld!
>
> being written, because the whitespace character gets trimmed down to
> nothing.
>
>
>
> More promising looks the idea of getting the length of each passed
> string and truncating before outputting:
>
>
> WRITE(*,*) (strings(i)(1:LEN(strings(i)), i = 1, SIZE(strings))
>
>
> However, as mentioned above, the strings all actually have the same
> internal length!

Have a look at LEN_TRIM.

>
>
>
> Is there any way to determine the "real" length of the strings passed
> through the array? If not, is there maybe another solution to my problem?
>
> Thanks in advance.
>
>
-- mecej4
From: Jovan Cormac on
mecej4 wrote:

> I put 'routine1' into the calling program source as a CONTAINed subroutine,
> and GFortran says:
>
> CALL routine1( (/ 'Hello', ' ', 'World!' /) )
> 1
> Error: Different CHARACTER lengths (5/1) in array constructor at (1)

Maybe this Fortran feature is not yet implemented in gfortran. Works
fine with Intel 11.1.054. Here's the entire code file, which as
mentioned compiles without errors or warnings with IVF:

PROGRAM test
CALL routine1( (/ 'Hello', ' ', 'World!' /) )
PAUSE

CONTAINS


SUBROUTINE routine1(strings)
IMPLICIT NONE

CHARACTER (LEN = *), INTENT(IN) :: strings(:)
INTEGER :: i

WRITE(*,*) (strings(i), i = 1, SIZE(strings))

RETURN
END SUBROUTINE routine1

END PROGRAM test



> Have a look at LEN_TRIM.

I've tried that already, it's the same problem. LEN_TRIM(string) is just
an alias for LEN(TRIM(string)), therefore it will return not the length
of the argument, but the length of the argument with trailing whitespace
removed, which would give the same result (and problems) as using TRIM
in the first place.



--
-- jovan
From: fj on
On 5 juin, 10:48, Jovan Cormac <limu...(a)gmx.net> wrote:
> I have a subroutine that accepts an array of variable-length strings of
> variable size (assumed-shape array) and is to output all of those strings:
>
>    SUBROUTINE routine1(strings)
>      IMPLICIT NONE
>
>      CHARACTER (LEN = *), INTENT(IN) :: strings(:)

This statement declares a vector of "fixed" length strings, the common
length of these strings being declared in the calling routine.

>      INTEGER :: i
>
>      WRITE(*,*) (strings(i), i = 1, SIZE(strings))
>
>      RETURN
>    END SUBROUTINE routine1
>
> If I call this subroutine using e.g.
>
> CALL routine1( (/ 'Hello', ' ', 'World!' /) )

This instruction is not legal : all the strings must have the same
length ! Your compiler has accepted it (extension) in padding the
shortest strings with spaces.

>
> I get the following output:
>
> Hello         World!
>
> As it turns out, the array "strings" is not actualy an array of
> variable-length strings as I want it to be, but rather an array of
> *fixed-length strings the length of the longest string passed*.
>
> Therefore, the single character ' ' gets inflated to match the length of
> the other two strings.
>
> The obvious hack to go around this is to TRIM the strings before
> outputting them:
>
>      WRITE(*,*) (TRIM(strings(i)), i = 1, SIZE(strings))
>
> However, in the above case, this of course results in:
>
> HelloWorld!
>
> being written, because the whitespace character gets trimmed down to
> nothing.
>
> More promising looks the idea of getting the length of each passed
> string and truncating before outputting:
>
>      WRITE(*,*) (strings(i)(1:LEN(strings(i)), i = 1, SIZE(strings))
>
> However, as mentioned above, the strings all actually have the same
> internal length!
>
> Is there any way to determine the "real" length of the strings passed
> through the array? If not, is there maybe another solution to my problem?
>
> Thanks in advance.
>
> --
> -- jovan

From: fj on
On 5 juin, 15:09, fj <francois.j...(a)irsn.fr> wrote:
> On 5 juin, 10:48, Jovan Cormac <limu...(a)gmx.net> wrote:
>
> > I have a subroutine that accepts an array of variable-length strings of
> > variable size (assumed-shape array) and is to output all of those strings:
>
> >    SUBROUTINE routine1(strings)
> >      IMPLICIT NONE
>
> >      CHARACTER (LEN = *), INTENT(IN) :: strings(:)
>
> This statement declares a vector of "fixed" length strings, the common
> length of these strings being declared in the calling routine.
>
> >      INTEGER :: i
>
> >      WRITE(*,*) (strings(i), i = 1, SIZE(strings))
>
> >      RETURN
> >    END SUBROUTINE routine1
>
> > If I call this subroutine using e.g.
>
> > CALL routine1( (/ 'Hello', ' ', 'World!' /) )
>
> This instruction is not legal : all the strings must have the same
> length ! Your compiler has accepted it (extension) in padding the
> shortest strings with spaces.

Correction : not legal in FORTRAN-95
>
>
>
> > I get the following output:
>
> > Hello         World!
>
> > As it turns out, the array "strings" is not actualy an array of
> > variable-length strings as I want it to be, but rather an array of
> > *fixed-length strings the length of the longest string passed*.
>
> > Therefore, the single character ' ' gets inflated to match the length of
> > the other two strings.
>
> > The obvious hack to go around this is to TRIM the strings before
> > outputting them:
>
> >      WRITE(*,*) (TRIM(strings(i)), i = 1, SIZE(strings))
>
> > However, in the above case, this of course results in:
>
> > HelloWorld!
>
> > being written, because the whitespace character gets trimmed down to
> > nothing.
>
> > More promising looks the idea of getting the length of each passed
> > string and truncating before outputting:
>
> >      WRITE(*,*) (strings(i)(1:LEN(strings(i)), i = 1, SIZE(strings))
>
> > However, as mentioned above, the strings all actually have the same
> > internal length!
>
> > Is there any way to determine the "real" length of the strings passed
> > through the array? If not, is there maybe another solution to my problem?
>
> > Thanks in advance.
>
> > --
> > -- jovan
>
>

 |  Next  |  Last
Pages: 1 2 3 4 5 6 7
Prev: many runs in one directory
Next: pressure and fortran