Prev: many runs in one directory
Next: pressure and fortran
From: Jovan Cormac on 5 Jun 2010 04:48 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 5 Jun 2010 07:15 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 5 Jun 2010 09:05 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 5 Jun 2010 09:09 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 5 Jun 2010 09:16
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 > > |