Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Q] Concatenating strings in FORTRAN 77

1,009 views
Skip to first unread message

Wim Van Paepegem

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to

Hello,

I want to concatenate two strings, but I don't know a priori how long
the strings will be ( the strings are the output from another program
and are respectively read in from a file and handed over by command
line.
When I want to concatenate these strings, I always get spaces in
between.
The declarations are the following :

INTEGER status, system, len1
CHARACTER*30 command
CHARACTER*30 commandline1
CHARACTER*60 whole_command
opdracht = './start '
len1 = LEN(opdracht)
PRINT *, opdracht, len1
commandline1 = '830fiber'
whole_command = opdracht // commandline1
PRINT *, whole_command

Because of the declaration "CHARACTER*30 command", the characters after
'./start ' are filled up with spaces and the concatenation is not good.
Moreover the 'LEN'-command gives '30' and not the actual size of the
string.
How can you solve this problem ?

With best regards,
Wim Van Paepegem
--

----------------------------------------
Wim Van Paepegem
Aspirant F.W.O.

University of Ghent
Mechanica van Materialen en Constructies
Sint-Pietersnieuwstraat 41
9000 Gent
Belgium
Tel: +32-09-264.42.07
Fax: +32-09-264.35.87
E-mail : Wim.Van...@rug.ac.be
----------------------------------------

Michael Metcalf

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
'./start ' are filled up with spaces and the concatenation is not
good.
Moreover the 'LEN'-command gives '30' and not the actual size of
the
string.
How can you solve this problem ?
=========================================================
Well, *you* can solve it by writing a little function called TRIM
that removes trailing blanks from a string. Alternatively, you
could try switching to a modern f90 compiler that has that built
in as an intrinsic function.

Regards,

Mike Metcalf

--

Helmut Mann

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
Wim Van Paepegem <Wim.Van...@rug.ac.be> wrote in message
news:3822DF02...@rug.ac.be...

>
> Hello,
>
> I want to concatenate two strings, but I don't know a priori how long
> the strings will be ( the strings are the output from another program
> and are respectively read in from a file and handed over by command
> line.
> When I want to concatenate these strings, I always get spaces in
> between.
> The declarations are the following :
>
> INTEGER status, system, len1
> CHARACTER*30 command
> CHARACTER*30 commandline1
> CHARACTER*60 whole_command
> opdracht = './start '
> len1 = LEN(opdracht)
> PRINT *, opdracht, len1
> commandline1 = '830fiber'
> whole_command = opdracht // commandline1
> PRINT *, whole_command
>

Use intrinsic function TRIM:

whole_command = TRIM(opdracht) // commandline1

--
Helmut Mann
mann_eng...@compuserve.com


Wim Van Paepegem

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to Helmut Mann

Helmut Mann wrote:

> Use intrinsic function TRIM:
>
> whole_command = TRIM(opdracht) // commandline1
>

Hello, Mr. Mann,

well, if it was that simple, I have found it myself :-).
I use the Sun Workshop f77 compiler and that compiler does not recognize
the TRIM function at all.

Regards,
Wim

Richard Maine

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
Michael Metcalf <11354...@CompuServe.COM> writes:

A few extra points.

1. It may sound like "just picking at words", but if you don't get
the concept right, you (the original poster - I'm very sure that
Mike understands) will have continuing problems with understanding
Fortran character handling...

The 30 *IS* the actual size of the string. Period. If you declare
a string to be of length 30 then it has *EXACTLY* that length, never
any more and never any less. When you assign it with a value that
has some other length, the data is truncated or blank-padded to
the length 30. Those blanks are part of the string and are just
as ordinary a part as any other characters.

(Thus the LEN intrinsic is "uninteresting" in many cases; you use
it mostly for things like assumed length dummy arguments).

2. As Mike mentions, f90 has the TRIM intrinsic for exactly this, but
f77 doesn't.

3. You won't find it particularly easy to write TRIM as a user-written
function. In fact, I don't tthink I recall how to do it. I think
I recall seeing an example of how, but it is not *AT ALL* simple.

What is, however, easy is to write a function (like the f90 len_trim)
that returns an integer with the length of the non-blank part of the
string. Then use that length to write a substring as in

l = len_trim(opdracht)
whole_command = opdracht(:l) // commandline1

--
Richard Maine
ma...@altair.dfrc.nasa.gov

Ken Plotkin

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
On Fri, 05 Nov 1999 16:26:30 +0100, Wim Van Paepegem
<Wim.Van...@rug.ac.be> wrote:


>well, if it was that simple, I have found it myself :-).
>I use the Sun Workshop f77 compiler and that compiler does not recognize
>the TRIM function at all.

See if it has len_trim or lentrim. I've seen that as an extension in
some F77 compilers for some time.

If not, then write one as Richard suggests. The method is to look for
a non-blank, starting at the back:


integer function ltrim(string,length)
character*(*) string
do 10, i = length,1,-1
if(string(i:i).ne.' ') go to 20
10 continue
20 continue
ltrim = i
return
end

The "if" will need to be more elaborate if the string could be filled
with stuff other than blanks.

Ken Plotkin

Jeffrey J. Potoff

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
Wim Van Paepegem wrote:
>
> Helmut Mann wrote:
>
> > Use intrinsic function TRIM:
> >
> > whole_command = TRIM(opdracht) // commandline1
> >
>
> Hello, Mr. Mann,
>
> well, if it was that simple, I have found it myself :-).
> I use the Sun Workshop f77 compiler and that compiler does not recognize
> the TRIM function at all.
>

See if it has LEN_TRIM. That will give you the length of the
string minus the trailing blanks. Then you can do something like

character*60 foobar,foo,bar

foobar = foo(1:len_trim(foo))//bar(1:len_trim(bar))

Jeff

James Giles

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to

Richard Maine wrote in message ...
...

>3. You won't find it particularly easy to write TRIM as a user-written
> function. In fact, I don't tthink I recall how to do it. I think
> I recall seeing an example of how, but it is not *AT ALL* simple.

I'd like anyone who knows this technique to post it. I can't imagine
how it would work.

--
J. Giles

James Giles

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to

Carsten A. Arnholm wrote in message ...
>
>James Giles wrote in message <7vvf6d$6sn$1...@bgtnsc02.worldnet.att.net>...
>An approximation is:

Well, that's the alternative Richard Maine mentioned to avoid having
to write the TRIM function. What I'm interested in is actually writing
a TRIM function (if that's possible). That is, a function returning a
character string whose length depends on the value of its arguments
(or some other run-time information). If there's really a way, as Richard
Maine suggests there might be, I'd like to see it.

It is fairly trivial to write a function that returns an integer that specifies
a substring bound which you can then apply to the original string. That's
not what Richard Maine was talking about.

--
J. Giles

James Giles

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to

James Giles wrote in message <8000k0$a62$1...@bgtnsc01.worldnet.att.net>...
...

>Well, that's the alternative Richard Maine mentioned to avoid having
>to write the TRIM function. What I'm interested in is actually writing
>a TRIM function (if that's possible). That is, a function returning a
>character string whose length depends on the value of its arguments
>(or some other run-time information). If there's really a way, as Richard
>Maine suggests there might be, I'd like to see it.

By the way, I can already think of two ways to *nearly* achieve this.
One is to use the supplimentary standard for varying length strings.
This has the well known problem of causing memory leaks in most
implementations (since, when pointers go out of scope their target
is not deallocated). The other way is with a rather sophisticated
preprocessor which would generate code for the varying string
stuff *and* keep track of when things go out of scope so that
it could generate deallocations for it. Both these are outside
the Fortran 90 standard though (and certainly not possible within
any F77 implementation).

--
J. Giles

Kevin G. Rhoads

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
* code is mostly F77 except for longer than 6 character names
* Copyright 1999, Kevin G. Rhoads --
* Licensed under GNU Public License, v2.0 or later OR
* under GNU Library License, v2.0 or later at the
* discretion of the user
* N.B. - not optimized
*----------------------------------------------------------------------
integer function TRIMMED_LENGTH(ASTRING)
character*(*) ASTRING
integer i,j,len
character*1 char,space
intrinsic len,char
*-----
space = ' '
TRIMMED_LENGTH = len(ASTRING)
j = TRIMMED_LENGTH
do 1 i = TRIMMED_LENGTH,2,-1
* check for NUL terminator within string (useful in mixed Fortran/C coding)
if (ASTRING(i:i).eq.char(0)) then
j = i - 1
goto 2
endif
* check for non-blank -- could be modified to test for CR, LF or CR/LF
if (ASTRING(i:i).ne.space) then
j = i
goto 2
endif
1 CONTINUE
2 continue
TRIMMED_LENGTH = j
return
end
--
Kevin G. Rhoads, Ph.D. (The Cheshire Cat for official Internet mascot.)
kgrhoads@NO_SPAM.alum.mit.edu

Carsten A. Arnholm

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to

James Giles wrote in message <7vvf6d$6sn$1...@bgtnsc02.worldnet.att.net>...
>
>Richard Maine wrote in message ...
>...
>>3. You won't find it particularly easy to write TRIM as a user-written
>> function. In fact, I don't tthink I recall how to do it. I think
>> I recall seeing an example of how, but it is not *AT ALL* simple.
>
>I'd like anyone who knows this technique to post it. I can't imagine
>how it would work.

An approximation is:

PROGRAM MAIN
CHARACTER*40 TEXT
INTEGER I,TXTLEN
TEXT = 'Some text'
I=1
PRINT 10,TEXT,I
I=2
PRINT 10,TEXT(1:TXTLEN(TEXT)),I
10 FORMAT(1X,A,I1)
END

INTEGER FUNCTION TXTLEN(TEXT)
CHARACTER*(*) TEXT
C
C Calculate lenght of TXT excluding
C trailing blanks & null chars.
C
C Input:
C TEXT Text for which lenght shall be found.
C
C Result:
C Length of text excluding trailing blanks/nulls.
C
CHARACTER*1 NULL
INTEGER L,K
NULL = CHAR(0)
C
K = LEN(TEXT)
DO 100 L = K,1,-1
IF (TEXT(L:L).NE.' ' .AND. TEXT(L:L).NE.NULL) GOTO 110
100 CONTINUE
C
L = 0
110 CONTINUE
TXTLEN = L
C
RETURN
END


Robert Corbett

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to
In article <8000k0$a62$1...@bgtnsc01.worldnet.att.net>,

James Giles <james...@worldnet.att.net> wrote:
>
>Carsten A. Arnholm wrote in message ...
>>
>>James Giles wrote in message <7vvf6d$6sn$1...@bgtnsc02.worldnet.att.net>...
>>>
>>>Richard Maine wrote in message ...
>>>...
>>>>3. You won't find it particularly easy to write TRIM as a user-written
>>>> function. In fact, I don't tthink I recall how to do it. I think
>>>> I recall seeing an example of how, but it is not *AT ALL* simple.
>>>
>>>I'd like anyone who knows this technique to post it. I can't imagine
>>>how it would work.
>>
>>An approximation is:
>
>Well, that's the alternative Richard Maine mentioned to avoid having
>to write the TRIM function. What I'm interested in is actually writing
>a TRIM function (if that's possible). That is, a function returning a
>character string whose length depends on the value of its arguments
>(or some other run-time information). If there's really a way, as Richard
>Maine suggests there might be, I'd like to see it.
>
>It is fairly trivial to write a function that returns an integer that specifies
>a substring bound which you can then apply to the original string. That's
>not what Richard Maine was talking about.
>
>--
>J. Giles

Intrinsic functions are special. A user cannot write a function equivalent
to TRIM in Fortran 95.

This special treatment is not new. Even in FORTRAN 77, a user could not
write a routine equivalent to MAX.

Sincerely,
Bob Corbett

James Giles

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to

Robert Corbett wrote in message <800gm8$dg3$1...@engnews1.eng.sun.com>...
...

>Intrinsic functions are special. A user cannot write a function equivalent
>to TRIM in Fortran 95.
>
>This special treatment is not new. Even in FORTRAN 77, a user could not
>write a routine equivalent to MAX.

That's what I would have thought. But comments from Richard Maine, even
when he refers to vaguely remembered ideas, cannot be dismissed out of hand.

--
J. Giles

Jean Vezina

unread,
Nov 7, 1999, 3:00:00 AM11/7/99
to
Robert Corbett wrote:
>
> In article <8000k0$a62$1...@bgtnsc01.worldnet.att.net>,
> James Giles <james...@worldnet.att.net> wrote:
> >
> >Carsten A. Arnholm wrote in message ...
> >>
> >>James Giles wrote in message <7vvf6d$6sn$1...@bgtnsc02.worldnet.att.net>...
> >>>
> >>>Richard Maine wrote in message ...
> >>>...
> >>>>3. You won't find it particularly easy to write TRIM as a user-written
> >>>> function. In fact, I don't tthink I recall how to do it. I think
> >>>> I recall seeing an example of how, but it is not *AT ALL* simple.
> >>>
> >>>I'd like anyone who knows this technique to post it. I can't imagine
> >>>how it would work.
> >>
> >>An approximation is:
> >
> >Well, that's the alternative Richard Maine mentioned to avoid having
> >to write the TRIM function. What I'm interested in is actually writing
> >a TRIM function (if that's possible). That is, a function returning a
> >character string whose length depends on the value of its arguments
> >(or some other run-time information). If there's really a way, as Richard
> >Maine suggests there might be, I'd like to see it.
> >
> >It is fairly trivial to write a function that returns an integer that specifies
> >a substring bound which you can then apply to the original string. That's
> >not what Richard Maine was talking about.
> >
> >--
> >J. Giles
>
> Intrinsic functions are special. A user cannot write a function equivalent
> to TRIM in Fortran 95.

On the contrary, it's possible:

FUNCTION MYTRIM(ARG)
CHARACTER(*) ARG
CHARACTER(LEN_TRIM(ARG)) MYTRIM
MYTRIM = ARG
END FUNCTION

Regards,

Jean Vezina

James Giles

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to

Jean Vezina wrote in message <382629...@ibm.net>...
...

>> Intrinsic functions are special. A user cannot write a function equivalent
>> to TRIM in Fortran 95.
>
>On the contrary, it's possible:
>
>FUNCTION MYTRIM(ARG)
>CHARACTER(*) ARG
>CHARACTER(LEN_TRIM(ARG)) MYTRIM
>MYTRIM = ARG
>END FUNCTION

Interesting notion. I don't think the length of a procedure argument
is the kind of thing allowed in an initialization expression, much less a
KIND or LEN attribute specification. But it's worth investigating.

--
J. Giles

James Giles

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to

Jean Vezina wrote in message <382629...@ibm.net>...
...
>FUNCTION MYTRIM(ARG)
>CHARACTER(*) ARG
>CHARACTER(LEN_TRIM(ARG)) MYTRIM
>MYTRIM = ARG
>END FUNCTION

This, as written, is not permitted. The LEN_TRIM function is
not among the functions permitted in a specification expression.
However, both LEN and TRIM are permitted. So, LEN(TRIM(ARG))
should be acceptable. That appears to be the solution unless there's
some additional constraint my tired eyes can't find this time of night.
Good idea!

Now, I wonder how many implemenations actually do allow this?

--
J. Giles

James Giles

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to
Jean Vezina wrote in message <382629...@ibm.net>...
...
>> Intrinsic functions are special. A user cannot write a function equivalent
>> to TRIM in Fortran 95.
>
>On the contrary, it's possible:
>
>FUNCTION MYTRIM(ARG)
>CHARACTER(*) ARG
>CHARACTER(LEN_TRIM(ARG)) MYTRIM
>MYTRIM = ARG
>END FUNCTION

LEN_TRIM *is* allowed as an specification expression (since it is
an elemental intrinsic function). So the above will actually work.

To show how silly you can get late at night after a particularly silly
dinner party, I actually wrote and posted an article suggesting the
following: Both LEN and TRIM are allowed, so, although it's possible
to write the function declared as:

CHARACTER(len(trim(arg))) NYTRIM

This is obviously just silly. It is not really a good notion to
define your own trim in terms of the built-in trim. If you read
that before the cancellation reaches your news server, you can
have a good laugh at my expense.:-)

In any case, the original question was how to do this in F77.
So, even if F90 or F95 allowed LEN_TRIM in a specification
expression, it is clearly not allowed in F77 (which doesn't even
have the LEN_TRIM intrinsic at all).

--
J. Giles


Tony T. Warnock

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to
Jean Vezina wrote:

> > Intrinsic functions are special. A user cannot write a function equivalent
> > to TRIM in Fortran 95.
>
> On the contrary, it's possible:
>
> FUNCTION MYTRIM(ARG)
> CHARACTER(*) ARG
> CHARACTER(LEN_TRIM(ARG)) MYTRIM
> MYTRIM = ARG
> END FUNCTION
>

> Regards,
>
> Jean Vezina

In Fortran 77, Len_Trim is a user function, not an intrinsic. I do not think you can
use user functions in specifications. How is MYTRIM declared and called in the caller
program?

I always did this the hard way:

...caller subroutine...
...
INTEGER Len_Trim
EXTERNAL Len_Trim
...
...references using Len_Trim: a(1:Len_Trim(a))...
...
END
FUNCTION Len_Trim(a)
INTEGER Len_Trim, i
CHARACTER*(*) a
DO 10 i=1,Len(a),-1
IF (a(i:i).NE.' ') GO TO 20
10 CONTINUE
20 CONTINUE
Len_Trim=i-1
END

I couldn't write Trim() but I could get the functionality. Most of my stuff has the
above as I haven't converted them to Fortran90 yet (takes too much work.)


Malcolm Cohen

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to
In article <800gm8$dg3$1...@engnews1.eng.sun.com>,

Robert Corbett <cor...@lupa.Sun.COM> wrote:
>Intrinsic functions are special. A user cannot write a function equivalent
>to TRIM in Fortran 95.

Yes, intrinsic functions are special - but TRIM is not one of the special
ones.

Here is a Fortran90 version:

FUNCTION mytrim(ch)
CHARACTER*(*),INTENT(IN) :: ch
CHARACTER*(LEN_TRIM(ch)) :: mytrim
mytrim = ch
END FUNCTION

This looks to me like it implements "TRIM".

Not much help to the original poster though, since he wanted F77. Oh well.

Cheers,
--
...........................Malcolm Cohen, NAG Ltd., Oxford, U.K.
(mal...@nag.co.uk)

Richard Maine

unread,
Nov 9, 1999, 3:00:00 AM11/9/99
to
"James Giles" <james...@worldnet.att.net> writes:

> Robert Corbett wrote in message <800gm8$dg3$1...@engnews1.eng.sun.com>...
> ...

> >Intrinsic functions are special. A user cannot write a function equivalent
> >to TRIM in Fortran 95.
>

> That's what I would have thought. But comments from Richard Maine, even
> when he refers to vaguely remembered ideas, cannot be dismissed out of hand.

Thanks for the expression of confidence, misplaced though it may be.
Though I certainly can't get 'em right 100% of the time, perhaps I
can try to live up to the confidence by admitting when I goof; I
can't get that one 100% either, but I can come closer.

Alas, it appears that I must have been confusing two different things.
I was half expecting that someone would repost whatever it was that I
recalled; I'm sure that it was here that I saw whatever it is I'm
remembering.

But on reading the followups and then thinking further, I conclude

1. Its embarassingly trivial in f90, as illustrated by some of the
samples posted. Doesn't seem particularly useful (since if you have
f90, you have the intrinsic TRIM), but its trivial to do. That doesn't
match whatever it is I was remembering.

2. I'm now convinced that it isn't possible at all in f77 (within the
language). I can't even see an avenue that provides an oportunity
for exploitation like specification expressions do in f90.

(There, now that I said I'm convinced its impossible, that should
drag up a counterexample if there really is one).

My recollections included one posting that involved using TRANSFER to
turn a character string into an array of characters, and then using
array operations, and I think the MERGE intrinsic got in there
somewhere. Really tricky...or anyway I thought so. Must have been
for a different problem than replicating TRIM, however. I'm trying to
recall what problem it was, but its just not "coming" at the moment.

--
Richard Maine
ma...@altair.dfrc.nasa.gov

Robert Corbett

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to
In article <382629...@ibm.net>, Jean Vezina <jve...@ibm.net> wrote:

>Robert Corbett wrote:
>>
>On the contrary, it's possible:
>
>FUNCTION MYTRIM(ARG)
>CHARACTER(*) ARG
>CHARACTER(LEN_TRIM(ARG)) MYTRIM
>MYTRIM = ARG
>END FUNCTION
>
>Regards,
>
>Jean Vezina

Very nice. I had not considered using LEN_TRIM in the declaration.

Sincerely,
Bob Corbett

Clive Page

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to
In article <ueaeonf...@altair.dfrc.nasa.gov>,
Richard Maine <ma...@altair.dfrc.nasa.gov> wrote:

>2. I'm now convinced that it isn't possible at all in f77 (within the
> language). I can't even see an avenue that provides an oportunity
> for exploitation like specification expressions do in f90.

I agree with you - I also think it's impossible.

>My recollections included one posting that involved using TRANSFER to
>turn a character string into an array of characters, and then using
>array operations,

Perhaps what you remember is some code I posted once, not entirely
seriously, to solve the problem of turning an integer into a
left-justified string of digits. This turns out to be quite easy in f95,
impossible in f77, but just possible in f90 if you declare the function
argument like this:

CHARACTER(LEN=12 - MAX(0,SIGN(1,intval)) - VERIFY(TRANSFER(ACHAR(48+ &
(/(MOD(MAX(1,ABS(intval))/10**n,10),n=9,0,-1)/) ), &
"1234567890"), ACHAR(48)) ) :: string

which is valid Fortran, but gave indigestion to one or two compilers.
Other people found alternative ways of doing this, conceptually simpler
but actually longer.
--
Clive Page, e-mail: cgp (at) le (dot) ac (dot) uk
Dept of Physics & Astronomy,
University of Leicester.

Richard Maine

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to
Clive Page <c...@nospam.le.ac.uk> writes:

Yes. That was it. I recognize it, even if I couldn't duplicate it.
Not that I've actually worked through it completely to verify that it
works as advertised, but I can believe that it does. I see that it
shares with TRIM the property of returning a string with a length that
depends on the value of an argument. That's probably the connection
that was making me vaguely recall this.

--
Richard Maine
ma...@altair.dfrc.nasa.gov

0 new messages