1-13 PROGRAM INPUT AND OUTPUT
*****************************
Input files - an efficient way to read data
-------------------------------------------
Input files are a popular and efficient way to pass parameters and
initial values to a program.
Input files should include detailed comments, so you can easily
identify all input values, and any deviation from the allowed ranges.
Interactive programs that get input from the user should save
this data into a "configuration file" that can be read later.
Multi-block input files
-----------------------
If the input values are arranged in a documented "block", like the
one in the following example, then an "open loop" in the program
can read and execute several such "blocks" one after another until
it gets to the end of the input file:
!------------------------------------------------------------------------
! NSTEP Number of time steps
1000
!------------------------------------------------------------------------
! X1 X2 Time range of integration
0.000D+000 1.000D+000
!------------------------------------------------------------------------
! K A useful constant
0.333D-000
!------------------------------------------------------------------------
! EPS Accuracy required
0.100D-003
A code excerpt implementing an "open loop" for processing several
consecutive "input blocks" like the one showed above:
100 continue
read(unit=10, fmt='(/)', err=998, end=999)
read(unit=10, fmt=*, err=998, end=999) nstep
read(unit=10, fmt='(/)', err=998, end=999)
read(unit=10, fmt=*, err=998, end=999) x1, x2
read(unit=10, fmt='(/)', err=998, end=999)
read(unit=10, fmt=*, err=998, end=999) k
read(unit=10, fmt='(/)', err=998, end=999)
read(unit=10, fmt=*, err=998, end=999) eps
call compute(nstep, x1, x2, k, eps)
goto 100
998 stop ' error reading input file '
999 stop ' end of input file '
XDR - Portable binary files
---------------------------
HDF - A de facto standard for data files
----------------------------------------
Using checkpoints to safeguard long calculations
------------------------------------------------
Programs doing long calculations that may take hours or more, should
use checkpoints, as a safeguard against system crashes and unexpected
program aborts that may trash the output files.
On every reasonable time interval, or when the program reaches some
naturally defined dividing point, all essential data should be written
to a special file (sometimes called 'basic point').
The data written to the file should be sufficient to continue the
computation from the point reached when the data was dumped.
Flushing sequential output files at run-time
--------------------------------------------
It is useful to inspect the intermediary results of programs that
take a long time to run, if a serious error is found the program
can be aborted, and the error rectified without wasting more time.
If the results are written to a files, you may have a problem
inspecting them, the output of your program may be left in the
buffers assigned by the system or I/O run-time library, until
it is appropriate to "flush" the contents into the disk.
There is no system-independent method to overcome this problem,
some methods used are:
1) Closing the file, opening it again in "append mode"
(non-standard! may be implemented with OPEN keywords
like: ACCESS='APPEND', or POSITION='APPEND'),
and resume writing to it
2) Using FORTRAN statements like: ENDFILE and BACKSPACE.
On some systems (e.g. AIX) they cause flushing
3) Using routines from an optional FORTRAN library,
e.g. "flush" from the "libU77" library.
4) Using Standard C functions like "fflush", "fseek".
fseek(lun, 0,1) works on HP systems.
5) Using POSIX routines: "PXFFFLUSH"
6) Using special "system calls", e.g. "fsync" or
"sync" on UNIX (preferably with a FORTRAN binding),
"SYS$FLUSH" on VMS.
By the way, running a program in batch mode on VMS, you can
write your output to the "log file" using WRITE (*,...).
The log file is frequently and automatically flushed to disk.
Reading FORTRAN expressions
---------------------------
You can read numbers (into a numeric variable) or strings (into a
character variable) from the keyboard/file but not a function.
Functions must be defined in FUNCTION procedures (or be intrinsics,
i.e. pre-defined).
The Fortran EXTERNAL statement wouldn't help in this case, it just
tells the compiler that the following identifier is a subroutine or
function, and lets you pass it to another procedure as an argument.
It would be a nice FORTRAN extension if we could read an expression
into a character string, and have the program compute its value for
given values of the argument(s).
Such a capability could be useful, if you had a simulation program
requiring a lot of initial data that can be computed from some
mathematical expressions. Using a "function reader" you could try
various initial input sets for the program without having to write
special routines, or running programs for preparing the initial input.
By the way, interactive plotting programs usually have such a capability,
making it possible to study the behaviour of complex functions without
using analytical tools.
In order to appreciate what is involved in implementing such a "function
reader" extension, note that a FORTRAN function is an entity very
different from ordinary variables.
A function (or a mathematical expression) is really a list of instructions
for computing a number from one or more given numbers, i.e. a function is
a piece of machine code, not just a passive memory chunk you assign values
to like ordinary variables.
To compute the value of a function, something with functionality similar
to that of an interpreter (or compiler) is needed. Machine code that will
compute the values must be produced and run in some way (not necessarily
in a direct way). Producing the machine code involve complex stages like
parsing and code generation.
If you read a mathematical expression at run-time, it's already after
the compilation was finished, so the compiler can't parse the expression
for you, unless it planted a lot of parsing code in your program.
Return to contents page