[comp.lang.fortran] Any way to fseek

dmb@morgoth.UUCP (David M. Brown) (07/08/88)

[IBM-AT...MS-Fortran...MS-DOS]

I am writing an application which reads in data from a file.  I want
to be able to comment out lines of data.  I did this on my old system
(Ultrix on uVAX II) by using fseek().  It wasn't pretty but it worked.

What I want to do is look at the first character in the line, and, if 
it's a '#', just go on to the next line.  No problem there.  But, if it's
not, then I want to read data from the rest of the line.

The backslash edit descriptor doesn't seem to work on input.  The lines
in the file are of various lengths, so direct access won't work. 

Anyone have any ideas?

David Brown
{harvard | ll-xn | mirror}!adelie!morgoth!dmb
ICF Technology, Robinson Plaza II, Suite 200, Pittsburgh, PA  15205
(412) 788-9200

 WE CHALLENGE our traditions
      BECAUSE we believe
        TRUTH without questioning
     IS FALSE

seibel@cgl.ucsf.edu (George Seibel) (07/11/88)

In article <472@morgoth.UUCP> dmb@morgoth.UUCP (David M. Brown) writes:
>[IBM-AT...MS-Fortran...MS-DOS]

>I am writing an application which reads in data from a file.  I want
>to be able to comment out lines of data.  I did this on my old system
>(Ultrix on uVAX II) by using fseek().  It wasn't pretty but it worked.

>What I want to do is look at the first character in the line, and, if 
>it's a '#', just go on to the next line.  No problem there.  But, if it's
>not, then I want to read data from the rest of the line.

>The backslash edit descriptor doesn't seem to work on input.  The lines
>in the file are of various lengths, so direct access won't work. 

>Anyone have any ideas?

The usual approach is to read a line into a buffer, then test the buffer
to see if it has the characters that signify a real record.  If it does,
read it using an internal read.  In this example, I assume a max record
length of 80 chars, and read an integer and a real...

      parameter (LENREC=80)
      character*LENREC buffer
c
c     --- read a line into the buffer ---
c
      read(lunit,'(a)') buffer
c
c     --- read data from buffer if not comment ---
c
      if (buffer(1:1) .ne. '#') read(buffer,'(i5,f8.3)') idata, rdata
c
... that's all.  this is standard fortran 77, so you shouldn't have to
mess around with fseek(), and it should work on any fortran 77 compiler.
All you're doing here is substituting the name of a character variable
that contains your data for the logical unit number in an otherwise standard
read statement.  This method is simple and suffices for most applications.
You'll have to do formatted reads however; if you want to do a "free format
read" from the buffer, then you'll have to parse it yourself.

George Seibel, UCSF
seibel@cgl.ucsf.edu

richard@calvin.EE.CORNELL.EDU (Richard Brittain) (07/12/88)

In article <11041@cgl.ucsf.EDU> seibel@hegel.mmwb.ucsf.edu.UUCP (George Seibel) writes:
>In article <472@morgoth.UUCP> dmb@morgoth.UUCP (David M. Brown) writes:
>>What I want to do is look at the first character in the line, and, if 
>>it's a '#', just go on to the next line.  No problem there.  But, if it's
>>not, then I want to read data from the rest of the line.
>.........
>
>The usual approach is to read a line into a buffer, then test the buffer
>to see if it has the characters that signify a real record.  If it does,
>read it using an internal read.  In this example, I assume a max record
>length of 80 chars, and read an integer and a real...

   ....... example deleted

>... that's all.  this is standard fortran 77, so you shouldn't have to
>mess around with fseek(), and it should work on any fortran 77 compiler.
   .........
>You'll have to do formatted reads however; if you want to do a "free format
																					  ^^^^^^^^^^^
>read" from the buffer, then you'll have to parse it yourself.
 ^^^^
>George Seibel, UCSF
>seibel@cgl.ucsf.edu

This is a very common situation in a lot of the programming which I am
involved in, and I find the inability to perform a free format read from
a character string a constant frustration.  I never use a formatted read
when a free format read will do as this makes life so much easier.  Can
anyone explain a good reason for this rule in the fortran standard?  It has
always seemed somewhat arbitrary to me. 

Richard Brittain,                   School of Elect. Eng.,  Upson Hall   
                                    Cornell University, Ithaca, NY 14853
ARPA: richard@calvin.ee.cornell.edu	
UUCP: {uunet,uw-beaver,rochester,cmcl2}!cornell!calvin!richard

gil@mist.cs.orst.edu (Gil Bachelor) (07/13/88)

In article <490@calvin.EE.CORNELL.EDU> richard@calvin.ee.cornell.edu.UUCP 
   (Richard Brittain) writes:
>In article <11041@cgl.ucsf.EDU> seibel@hegel.mmwb.ucsf.edu.UUCP 
>   (George Seibel) writes:
>>In article <472@morgoth.UUCP> dmb@morgoth.UUCP (David M. Brown) writes:
>>>What I want to do is look at the first character in the line, and, if 
>>>it's a '#', just go on to the next line.  No problem there.  But, if it's
>>>not, then I want to read data from the rest of the line.
>>.........
>>The usual approach is to read a line into a buffer, then test the buffer
>>to see if it has the characters that signify a real record.  If it does,
>>read it using an internal read.  ...
>   ....... example deleted
>>... that's all.  this is standard fortran 77, so you shouldn't have to
>>mess around with fseek(), and it should work on any fortran 77 compiler.
>   .........
>>You'll have to do formatted reads however; if you want to do a "free 
>>format read" from the buffer, then you'll have to parse it yourself.
>>George Seibel, UCSF
>
>This is a very common situation in a lot of the programming which I am
>involved in, and I find the inability to perform a free format read from
>a character string a constant frustration.  I never use a formatted read
>when a free format read will do as this makes life so much easier.  Can
>anyone explain a good reason for this rule in the fortran standard?  It has
>always seemed somewhat arbitrary to me. 
>
>Richard Brittain,                   School of Elect. Eng.,  Upson Hall   
>                                    Cornell University, Ithaca, NY 14853

I don't know the reason for the rule.  However, some versions of Fortran
have been extended to allow free-format reads from internal files 
(character variables or arrays).  For those versions that don't allow it,
one can use a scratch file, as shown in this example:

      character line*80
      integer n
      real x

* Open unit 9 as a scratch file.
      open(9)

* Use A-format input to read an 80-character line into
*  variable "line".  
100   read (*,1000,end=200) line
1000  format(a)

* Test the first character of "line"; if it is a '#',
*  go somewhere else.
      if (line(1:1) .eq. '#') goto 150

* Use A-format to write the line on the scratch file and 
* read it back, using list-directed input.
      rewind(9)
      write(9,1000) line
      rewind(9)
      read (9,*) n, x
      ...

This may be considered a "kludge", but it works, and is a lot
easier than writing your own number-conversion routines.

------------------------------------------------------------------
Gilbert A. Bachelor      | Internet: gil@cs.orst.edu
Dept. of Computer Science|     UUCP: {hp-pcd,tektronix}!orstcs!gil
Oregon State University  |
Corvallis, OR  97331     | Phone:  (503) 754-3273

simon@alberta.UUCP (Simon Tortike) (07/15/88)

I'm responding to a request for processing comments at the start of lines
in a FORTRAN input text file.  Rather than reading the whole line in, I
always call a "get comment" subroutine that reads in the first character
of every line until it finds a line which is not commented out.  The routine
then backspaces one record and returns to the calling program.  The read
statements in the original program do not need to be altered, one only has
to call the comment-eater before reading in a record. Surely that's easier than
reading the entire line first?
FYI, I use the following code to inspect data for comments. As I said, a call
to this routine is made before reading a line of data, but it in no
way affects how the read is performed (e.g. the formatting.)

      character comment*1
      integer infile
      real foo(5)

      read (infile,'(a)',ERR=nnn) comment

      call getcmmt (infile, comment)
      read (infile, 666) foo(1), foo(2), foo(3), foo(4), foo(5)
 666  format (......

      subroutine getcmmt (unit, comment)
c     ********** *******
c     routine to inspect line start for comment character.
c     suggest using 'read (unit,'(a)',ERR=nnn) comment' as first
c     line before any input.  Then any character can serve as
c     a commented-line indicator by placing it in the first
c     column of the first line of the data file. see following routine.
c
      implicit logical (a-z)
      integer unit
      character thechar*1, comment*1
c
 100  read (unit,'(a)',err=998) thechar
      if (thechar .eq. comment) go to 100
      backspace (unit, err=999)
      return
 998  print *, ' Error reading unit ', unit, ' in "getcmmt"!!'
      return
 999  print *, ' Error backspacing unit ', unit, ' in "getcmmt"!!'
      return
      end
c
  -------------------
Simon Tortike
Dept Min, Met &    UUCP:   ...{ubc-vision,mnetor}!alberta!simon
  Petroleum Engg   BITNET: stortike@ualtavm
Univ. of Alberta   AGT:    403/432-3338
Edmonton, AB
Canada T6G 2G6
*** No nifty notes or quotes, I'm sorry to say ***

EACELARI@pucc.Princeton.EDU (Edward A Celarier) (07/17/88)

In article <1450@pembina.UUCP>, simon@alberta.UUCP (Simon Tortike) writes:
>                            .. Rather than reading the whole line in, I
>always call a "get comment" subroutine that reads in the first character
>of every line until it finds a line which is not commented out.  The routine
>then backspaces one record and returns to the calling program.  The read
>statements in the original program do not need to be altered, one only has
>to call the comment-eater before reading in a record. Surely that's easier than
>reading the entire line first?
 
 
Perhaps so, but if the particular implementation you are using literally
backspaces a device (not necessary for "blocked" files, unless the
records are particularly long), this can really slow things down!
 
I don't know the reason for the screwy Fortran standard, and, in fact, I
was a bit surprised.  All the machines I've been working on for the last
couple of years (VAX/VMS and Gould) have surreptitiously supported
reading free-formattedly from an internal file (character variable).

hirchert@uxe.cso.uiuc.edu (07/18/88)

Various people have asked why FORTRAN 77 doesn't allow list-directed input from
an internal file.  I wasn't a member of X3J3 when FORTRAN 77 was developed, but
I think I can offer an intelligent guess:
1. People would think it strange to allow list-directed input and not list-
   directed output, but list-directed output is distinctly nonportable
   because of the differences in output formats used for list-directed
   output.  (We're not just talking differences in what output looks like;
   we're talking differences in whether a program runs because the internal
   file may not be big enough to hold the generated output.)
2. Even list-directed input isn't as easy as some people think because of the
   difficulty in coping with the fact that list-directed input may or may not
   read additional records, depending on whether or not there were enough
   values on the first record.  If one does enough parsing to determine how
   many values appear on the record, then it isn't that much more work to
   construct a format to read them.

On the other hand, the draft Fortran 8x standard put out for public comment
removed these restrictions and I don't think anyone complained about that, so
eventually all Fortrans will probably let you do this (but that's no
consolation today).

Kurt W. Hirchert     hirchert@ncsa.uiuc.edu
National Center for Supercomputing Applications