[comp.lang.c] FORTRAN type I/O in C - Help!

griffin@prism.gatech.EDU (GRIFFIN,JEFFREY A) (06/27/91)

HELP! from a C guru urgently needed and appreciated.

I am looking for suggestions for reading a data file of which two 
records are listed below.  Each record consists of 512 characters 
plus a new-line.  There is an initial byte count of 0133 then 32 
integer values, another byte count of 0133 and 32 integers, the
last byte count of 0133 and the last 32 integers.  The remainder of
the record is padded with the '^' character.  The read would
certainly be more trivial if the last integer in each group was 
followed by a space before the next byte count.  In FORTRAN I would
read this as 3(I5, 32(I4)).  I would like to read each record into
a buffer string and then process the record.  In this way I can keep
better track of where I am in the file and track any possible
alignment errors when trying to read the file.

(1) What would be the best way to handle this?

(2) Has anyone written any I/O routines that are similar to doing
    formatted reads in FORTRAN?  For example a read command that
    supports the grouping of numbers i.e. 32%5d, etc.



0133   45  46  46  44  45  46  46  46  46  46  47  46  44  45  45
  45  47  46  45  46  46  45  45  46  46  47  46  46  46  46  46  
460133   46  46  46  46  46  47  47  47  47  47  47  46  46  46  46  
46  46  46  46  46  46  46  46  46  46  46  47  46  47  48  47  
470133   46  45  45  47  47  47  47  47  47  47  47  47  46  46  48  
47  47  47  46  45  47  47  46  47  47  46  46  47  46  46  46  
45^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0133   46  47  47  47  47  46  46  47  47  47  47  47  48  47  47  
46  46  46  47  47  46  47  47  45  46  46  46  46  46  46  47  
460133   46  48  47  47  47  46  47  48  46  47  46  45  47  47  47  
47  47  47  47  47  47  47  47  47  47  47  47  46  46  46  45  
470133   48  48  48  46  47  47  46  47  47  47  47  47  46  47  47  
46  47  47  46  47  47  45  46  47  47  47  47  46  47  47  45  
47^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- 
Griffin, Jeffrey A.
Georgia Institute of Technology, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!griffin
Internet: griffin@prism.gatech.edu

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/27/91)

In article <31839@hydra.gatech.EDU>, griffin@prism.gatech.EDU (GRIFFIN,JEFFREY A) writes:
> I am looking for suggestions for reading a data file of which two 
> records are listed below.  Each record consists of 512 characters 
> plus a new-line.  There is an initial byte count of 0133 then 32 
> integer values, another byte count of 0133 and 32 integers, the
> last byte count of 0133 and the last 32 integers.  The remainder of
> the record is padded with the '^' character.

What you have here is ANSI format for a tape with variable-length
records stored in 512-byte blocks.  The new-line is probably someone
trying to be helpful.  I suggest attacking this in two stages.

Stage 1:  break the file into records.

    int read_Record(FILE *f, char *buffer)	/* returns EOF */
	{					/* or strlen(buffer) */
	    int c;				/* EOF also means "error" */

	    /*  We should be at the beginning of a record. */
	    /*  Padding ^ characters and extra new-lines may intervene. */
	    do { do c = getc(f); while (c == '^'); } while (c == '\n');
	    /*  By now, only EOF and <four decimal digits> are ok.  */
	    if (c == EOF) return EOF;		/* real EOF; others=error */
	    ungetc(c, f);
	    if (fscanf(f, "%4d", &c) != 1 || c <= 0) return EOF;
	    if (fread(buffer, 1, c, f) != c) return EOF;
	    buffer[c] = '\0';
	    return c;
	}

Stage 2: parse the records using sscanf(), or, perhaps easier in this case,
strtol().
-- 
I agree with Jim Giles about many of the deficiencies of present UNIX.