[comp.lang.fortran] length of a character string

reeder@ut-emx.UUCP (William P. Reeder) (09/19/89)

I was porting NCAR Graphics (version 2.01) to an Alliant yesterday when
I got a compilation error on the third line of the following code
fragment:

	character*80 ncarg
	call getenv('NCARGLIB', ncarg)
	if (ncarg.eq."") then

A quick look in the standard confirmed that a character constant must
contain one or more characters between the apostrophies.  Yes, I know
that those are quotes up there; NCAR must be assuming that all compilers
allow quotes in place of apostrophies in addition to assuming that
everyone allows null strings and lower case letters.

Anyway, I need to check for a null string in variable "ncarg".  I thought
about using the intrinsic function LEN, but that just told me the
size of the character variable (80), not the length of the string stored
there (which may be less than 80).  Is this the proper behavior for LEN?
I can see where you would want to know how much storage was available
in a character variable, but I want to know the length of a string stored
in that variable much more frequently.  I didn't see any standard
intrinsic function defined which might give me this information.

The best idea I have come up with so far for creating a "null" string
is this:

	character*80 null
	write ( null, * )

Does anyone have any better ideas?
-- 
William "Wills" Reeder, The University of Texas at Austin, Computation Center
reeder@emx.utexas.edu, uunet!cs.utexas.edu!ut-emx!reeder, (512)471-3241

DISCLAIMER:     Opinions expressed above are those of the author and do
not necessarily reflect the opinions of The University of Texas at Austin,
or those of the manufacturer of the wires which carried this message.

maine@elxsi.dfrf.nasa.gov (Richard Maine) (09/20/89)

In article <18585@ut-emx.UUCP> reeder@ut-emx.UUCP (William P. Reeder) writes:

>  Anyway, I need to check for a null string in variable "ncarg".  I thought
>  about using the intrinsic function LEN, but that just told me the
>  size of the character variable (80), not the length of the string stored
>  there (which may be less than 80).  Is this the proper behavior for LEN?
>  I can see where you would want to know how much storage was available
>  in a character variable, but I want to know the length of a string stored
>  in that variable much more frequently.  I didn't see any standard
>  intrinsic function defined which might give me this information.

Yes, its behavior is correct.  The situation where I know that LEN is
of most use is in a subroutine with a character*(*) argument.  Of
course it can also be useful to avoid hard-coding constants multiple
places in the program so that later changes are easier.

There is no way (within the standard) to do what you are trying to
do.  FORTRAN 77 does not allow null strings in any context, so you
are not going to be able to come up with a standard way of making
or detecting them.

In fact, FORTRAN 77 has no concept of variable-length strings at all
(niether does 8x, if I recall correctly).  That's why LEN doesn't
do what you think, because FORTRAN 77 does not support the concept
you are thinking of.  The character*(*) arguments are not variable
length, though many people sloppily use such terminology for them
(the standard doesn't).

>  The best idea I have come up with so far for creating a "null" string
>  is this:

>          character*80 null
>          write ( null, * )

That won't work either, for 2 reasons.
  1) There ain't no such animal as a null string.  This will just
     fill the string with blanks, which is quite a different thing
     than a null string.
  2) List-directed i/o to internal files is illegal anyway.  Some
     compilers support it, but not all.  (8x does allow it).

>  Does anyone have any better ideas?

If you want to check for a blank string, that's easy, but I assume
you are making a distinction here.  If you really want to check
for null strings, its going to have to be outside of the context
of standard FORTRAN.  Perhaps there is a system call you can use
to get the required info instead of trying to get the string into
a FORTRAN string and then deduce things from that.
--

Richard Maine
maine@elxsi.dfrf.nasa.gov [130.134.1.1]

reeder@ut-emx.UUCP (William P. Reeder) (09/20/89)

In article <18585@ut-emx.UUCP>, I wrote:
> The best idea I have come up with so far for creating a "null" string
> is this:
> 
> 	character*80 null
> 	write ( null, * )
> 
> Does anyone have any better ideas?

Well, after a little more thought (and then someone wrote me a letter
with the same thoughts), it becomes clearer that FORTRAN has
BLANK strings, not NULL strings.  I came to this conclusion by
thinking about how character strings are compared with relational
operators: shorter strings are considered to be padded to the longer
length with blanks.  So, all I have to do is change
	if (ncar.eq."") then
with
	if (ncar.eq.' ') then
and everything is hunky-dory and standard conforming (except for those
lower-case letters :-).

Thanks for your time.
-- 
William "Wills" Reeder, The University of Texas at Austin, Computation Center
reeder@emx.utexas.edu, uunet!cs.utexas.edu!ut-emx!reeder, (512)471-3241

DISCLAIMER:     Opinions expressed above are those of the author and do
not necessarily reflect the opinions of The University of Texas at Austin,
or those of the manufacturer of the wires which carried this message.

bernhold@qtp.ufl.edu (David E. Bernholdt) (09/20/89)

In article <18585@ut-emx.UUCP> reeder@ut-emx.UUCP (William P. Reeder) writes:
>I was porting NCAR Graphics (version 2.01) to an Alliant...

>I thought about using the intrinsic function LEN, but that just told me the
>size of the character variable (80), not the length of the string stored
>there (which may be less than 80).

>I didn't see any standard
>intrinsic function defined which might give me this information.

Many (not all, however) UNIX Fortrans include a function called LNBLNK
in their library.  This returns the index of the "Last Non-BLaNK"
position in the string.

I just checked on an Alliant I have access to & its there.  It is also
present on Sun, Titan, Encore.  It is not present on Balance or Cray,
but for those and others it is quite easy to write in portable
Fortran77.  I have done this and use it in virtually all of my
programs -- its the only way to get nice formatting of strings.  I
would be glad to send a copy to anyone who's interested, but its only
14 lines of actual code!

BTW, the first public comment draft of the F8x standard included the same
function under a different name.  I don't know if its still there, but
I hope so!
-- 
David Bernholdt			bernhold@qtp.ufl.edu
Quantum Theory Project		bernhold@ufpine.bitnet
University of Florida
Gainesville, FL  32611		904/392 6365

brainerd@unmvax.unm.edu (Walt Brainerd) (09/20/89)

In article <676@orange19.qtp.ufl.edu>, bernhold@qtp.ufl.edu (David E. Bernholdt) writes:
> Many (not all, however) UNIX Fortrans include a function called LNBLNK
> in their library.  This returns the index of the "Last Non-BLaNK"
> position in the string.
> 
> 14 lines of actual code!
> 
> BTW, the first public comment draft of the F8x standard included the same
> function under a different name.  I don't know if its still there, but
> I hope so!

Here is the mentioned function in 14 / 2 lines.
Puzzle: even one of these lines is not necessary; which is it?
This also illustrates how the LEN function is useful in a subprogram.
It is still in F8x; the name is LEN_TRIM.
Kind of silly when it could be a part of a standardized string-handling module.

	FUNCTION LENTRM (STRING)
	CHARACTER *(*) STRING

	DO 10 LENTRM = LEN (STRING), 1, -1
	   IF (STRING (LENTRM:LENTRM) .NE. ' ') RETURN
   10	CONTINUE
	LENTRM = 0
	END

-- 
Walt Brainerd  Unicomp, Inc.           brainerd@unmvax.cs.unm.edu
               2002 Quail Run Dr. NE
               Albuquerque, NM 87122
               505/275-0800

userAKDU@ualtamts.BITNET (Al Dunbar) (09/20/89)

In article <MAINE.89Sep19132931@altair.dfrf.nasa.gov>, maine@elxsi.dfrf.nasa.gov (Richard Maine) writes:
>In article <18585@ut-emx.UUCP> reeder@ut-emx.UUCP (William P. Reeder) writes:
>
>>  Anyway, I need to check for a null string in variable "ncarg".  I thought
--- text deleted ---
>
>In fact, FORTRAN 77 has no concept of variable-length strings at all
>(niether does 8x, if I recall correctly).  ...
 
Correct! However, the German representatives to WG5 proposed such a thing.
Rather than putting it directly into  the  standard  at  this  late  date,
however,  a compromise was reached. The concept of "non-advancing I/O" was
added to 8X as a feature  that  would  facilitate  the  development  of  a
"standard  module"  that  could  provide  "varying  character" capability.
Without being party to the discussions that produced this proposal,  I  am
forced to conclude that it seems poorly thought out. It SHOULD have been a
more complete implementation of  "stream  I/O",  preferably  allowing  for
asynchronous,  character  at  a  time I/O with serial devices. The idea of
adding a marginally useful feature to the language just  to  simplify  the
development  of  a  useful  extension,  rather  than  adding the extension
itself, seems a particulary poor approach to the standardization process.
 
In article <18603@ut-emx.UUCP>, reeder@ut-emx.UUCP (William P. Reeder) writes:
>In article <18585@ut-emx.UUCP>, I wrote:
--- text deleted ---
>length with blanks.  So, all I have to do is change
>        if (ncar.eq."") then
>with
>        if (ncar.eq.' ') then
>and everything is hunky-dory and standard conforming (except for those
>lower-case letters :-).
 
That  is what I would have suggested to you. Unfortunately, there are some
situations in which the absence of  a  string  is  NOT  the  same  as  the
presence of a blank one. A case in point is the "environment variables" of
PC/MS-DOS and other systems. The code  you  suggest  would  be  unable  to
differentiate between the non- existence of the variable and its existence
with a "blank" value. To do that would require an interface to getenv that
provided  the  length  of the returned string. Alternately, you _might_ be
able to look for the null character terminating the string  returned  (IFF
that is how the string is indeed returned):
 
lencar = index( ncar, char(0) ) - 1
if (lencar .eq. 0) then
write (*,*) 'null string'
elseif(lencar .gt. 0) then
write (*,*) 'len=', lencar, ', string=(', ncar(:lencar), ')'
else
write (*,*) 'no null terminator'
endif
 
-------------------+-------------------------------------------
Alastair Dunbar    | Edmonton: a great place, but...
Edmonton, Alberta  | before Gretzky trade: "City of Champions"
CANADA             | after Gretzky trade: "City of Champignons"
-------------------+-------------------------------------------

userAKDU@ualtamts.BITNET (Al Dunbar) (09/21/89)

In article <676@orange19.qtp.ufl.edu>, bernhold@qtp.ufl.edu (David E. Bernholdt) writes:
>In article <18585@ut-emx.UUCP> reeder@ut-emx.UUCP (William P. Reeder) writes:
>>I was porting NCAR Graphics (version 2.01) to an Alliant...
--- text deleted ---
>
>BTW, the first public comment draft of the F8x standard included the same
>function under a different name.  I don't know if its still there, but
>I hope so!
 
It is still there, as LEN_TRIM, which is a bit more expressive
and 8x-like than my own LENNB (Non Blank LENgth).
-------------------+-------------------------------------------
Alastair Dunbar    | Edmonton: a great place, but...
Edmonton, Alberta  | before Gretzky trade: "City of Champions"
CANADA             | after Gretzky trade: "City of Champignons"
-------------------+-------------------------------------------

khb%chiba@Sun.COM (chiba) (09/21/89)

In article <2475@ualtamts.BITNET> userAKDU@ualtamts.BITNET (Al Dunbar) writes:
>
> varying length string discussion
> 
>Correct! However, the German representatives to WG5 proposed such a
>thing.

Such things have been repeatedly proposed over the last decade. The
German representive (singular) may have also done so .... but such
proposals predate his (and my) particpation in x3j3. There is a strong
feeling that the language is large enough (or too large :>) and that
varying length string modules are easily constructed (and, in fact,
jerry w. the vice-chair even showed one back in 1985)

>Rather than putting it directly into  the  standard  at  this  late  date,
>however,  a compromise was reached. The concept of "non-advancing
I/O" was

Has nothing to do with varying length string proposals. Non-advancing
IO was chosen in preference to "stream IO" during a protracted design,
review and debate process. I can't promise you it is better; but it
was chosen _after_ due deliberation.

>more complete implementation of  "stream  I/O",  preferably  allowing  for
>asynchronous,  character  at  a  time I/O with serial devices. The

Asynchronous IO is very hard to specify in a completely OS independent
fashion. The current proposal should cover character at a time (though
one expects there to be efficencies for grabing more per transaction)
and asynch extentions are probably planned by most of the vendors
whose operating systems support such things.

>development  of  a  useful  extension,  rather  than  adding the extension
>itself, seems a particulary poor approach to the standardization
>process.

True. But that isn't how it happened.


Keith H. Bierman    |*My thoughts are my own. !! kbierman@sun.com
It's Not My Fault   |	MTS --Only my work belongs to Sun* 
I Voted for Bill &  | Advanced Languages/Floating Point Group            
Opus                | "When the going gets Weird .. the Weird turn PRO"