home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
modula2
/
mod2txt.arc
/
CHAP8.TXT
< prev
next >
Wrap
Text File
|
1987-03-25
|
26KB
|
587 lines
Chapter 8 - Input/Output
A SIMPLE OUTPUT PROGRAM
Load and display the file named SIMPLOUT.MOD for an
example of the simple output functions. This program is
limited to writing only to the monitor but we will get to
files and printer output shortly. We must first establish
some basic principles for use with library procedures.
The first line of the declaration part of the program
imports our two familiar procedures "WriteString" and
"WriteLn" in the same manner we are used to. The next line
imports every procedure in "InOut" and makes them available
for use in the program without specifically naming each one
in the IMPORT list. The third line imports every procedure
from "Terminal" so that they too are available for our use.
The procedures that are imported explicitly can be used in
exactly the same manner that we have been using them all
along, simply name the procedure with any arguments they
use. The others can only be used with a "qualifier" that
tells which library module they come from.
An example is the easiest way to describe their use so
refer to the program before you. Line 11 uses the
explicitly defined procedure from "InOut", line 12 uses the
same procedure from "InOut", and line 15 uses the procedure
of the same name from "Terminal". Line 11 uses the
unqualified procedure call from "InOut", and lines 12 and 15
use the qualified method of calling the procedures from both
library modules.
In this case, the two procedures do the same thing, but
it is not required that procedures with the same name do the
same thing. By adding the library module name to the front
of the procedure name with a period between them, we tell
the system which of the two procedures we wish to use. If
we tried to explicitly import both "WriteString" procedures
we would get a compile error, so this is the way to use the
same name twice.
WHAT IS A LIBRARY MODULE?
What I have been calling a library module is more
properly termed a "module" and is the biggest benefit that
Modula-2 enjoys over other programming languages. This is
the quality that gives Modula-2 the ability to have
separately compiled modules, because a module is a
compilation unit. When you get to Part III of this
tutorial, you will learn how to write your own modules
containing your own favorite procedures, and call them in
any program in the same manner that you have been calling
the procedures provided by your compiler writer.
Page 49
Chapter 8 - Input/Output
None of the procedures you have been importing are part
of the Modula-2 language, they are extensions to the
language provided for you by your compiler writer. Since
they are not standard parts of the language, they may vary
from compiler to compiler. For that reason, I have tried to
use those defined by Niklaus Wirth in his definition of the
language, and no others.
STUDY YOUR REFERENCE MANUAL
This would be a good place for you to stop and spend
some time reading your reference manual. Look up the
section in your manual that is probably called the "Library"
and read through some of the details given there. You will
find that there are many things listed there that you will
not understand at this point, but you will also find many
things there that you do understand. Each module will have
a number of procedures that are "exported" so that you can
"import" them and use them. Each procedure will have a
definition of what arguments are required in order to use
it. Most of these definitions should be understandable to
you. One thing you will find is that only the "PROCEDURE
procname;" is given along with the arguments, with the
actual code of the procedure omitted. We will study about
this in "Part III" also. The part that is shown is the
"DEFINITION MODULE" which only gives the calling
requirements. The "IMPLEMENTATION MODULE" which gives the
actual program code of the procedure is usually not given by
compiler writers.
As you study the library modules, you will find
procedures to handle strings, variables and conversions
between the two. You will find "mouse" drivers, "BIOS"
calls to the inner workings of your operating system, and
many other kinds of procedures. All of these procedures are
available for you to use in your programs. They have been
written, debugged, and documented for your use once you
learn to use them. In addition, you will have the ability
to add to this list by creating your own modules containing
your own procedures.
BACK TO THE PROGRAM "SIMPLOUT"
Notice that in lines 13, 17, and 22, three different
ways are used to call "WriteLn", even though there are
actually only two procedures (that happen to do the same
thing). A little time spent here will be time well spent in
preparing for the next few programs. When you think you
understand this program, compile and run it.
Page 50
Chapter 8 - Input/Output
NOW FOR SOME SIMPLE INPUT PROCEDURES
Load the program named SIMPLIN.MOD for our first
example of a program with some data input procedures. In
every program we have run so far in this tutorial, all data
has been stored right in the program statements. It would
be a very sad computer that did not have the ability to read
variable data in from the keyboard and files. This program
is our first that can read from an external device, and it
will be limited to only the keyboard.
This program is broken up into four groups of
statements, each illustrating some aspect of reading data
from the keyboard. This could have been four separate files
but it will be easier to compile and run one file.
Beginning with line 14 we have an example of the
"ReadString" procedure which reads characters until it
receives a space, a tab, a return, or some other
nonprintable character. This loop will read three words on
one line, one word on each of three lines, or any
combination to get three words of groups of printable ASCII
characters. After each word or group is read, it is simply
"printed" to the monitor for your inspection.
ONE CHARACTER AT A TIME
The next group of statements is a loop in which 50
ASCII characters are read in and immediately echoed out to
the monitor. It should be evident to you that the
characters are read one at a time, and since the same
variable is used for each character, they are not stored or
saved in any way. In actual practice, the characters would
be stored for whatever purpose you intend to use them for.
When you run this part of the program, it will seem like the
computer is simply acting like a word processor, echoing
your input back to the monitor.
ONE LINE AT A TIME
The next section, beginning in line 32, reads in a full
line before writing it out to the monitor. In this program
we are introduced to the "EOL" which is a constant defined
by the system for our use. It must be imported from "InOut"
just like the procedures are, and it is a constant that is
equal to that ASCII value that is returned when we hit the
"return" key. It is therefore equal to the End-Of-Line
character, and that is how it got its name. If we compare
the input character to it, we can determine when we get to
the End-Of-Line. That is exactly what this loop does. It
continues to read characters until we find an EOL, then it
Page 51
Chapter 8 - Input/Output
terminates the input loop and displays the line of data.
Notice that this time we do not simply read the data and
ignore it but instead add it character by character to the
ARRAY named "StringOfData". Of course, the next time
through the loop we overwrite it. The careful student will
also notice that, in line 45 we wrote a zero character in
the character of the line just past the end of the line.
The zero is to indicate the end-of-string for the string
handling procedures. This portion of the program is easy,
but will require a little time on your part to completely
dissect it.
READING IN SOME NUMBERS, CARDINAL
Beginning in line 51, we have an example of reading 6
CARDINAL numbers in a loop. The procedure "ReadCard" will,
when invoked by your program, read as many digits as you
give it. When it reads any character other than a 0 through
9, it will terminate and return the number to your calling
program. Notice that this time all 6 numbers are read in,
stored, and when all are in, they are all displayed on one
line. This should be easy for you to decipher.
COMPILING AND RUNNING THIS PROGRAM
There is no program that you have studied here that is
as important for you to compile and run as this one is. You
should spend considerable time running this program and
comparing the results with the listing. Enter some invalid
data when you are running the "ReadCard" portion of it to
see what it does. When you are running the "line at a time"
portion, try to enter more than 80 characters to see what it
will do with it. This is a good point for you to learn what
happens when errors occur. After you understand what this
program does, we will proceed to file input and output.
FILE INPUT/OUTPUT
Load and display the file named FILEIO.MOD for your
first file reading and writing. The library module named
"InOut" has the ability to either read and write from/to the
keyboard and monitor, or to read and write from/to files.
The program before you redirects the input and output to
files for an illustration of how to do it.
Line 16 requests the operator, namely you, to enter a
filename to be used for input. There is nothing different
about this statement than the others you have been using.
The next line requests the system to open a file for
inputting, and part of the procedure "OpenInput" is to go to
the keyboard waiting for the filename to be typed in. So
Page 52
Chapter 8 - Input/Output
the message in line 16 is in preparation for what we know
will happen in line 17. Whatever filename is typed in is
opened for reading if it is found on the disk. The "MOD" in
the parentheses is a default extension supplied, (this can
be any extension you desire). If no extension is supplied
by the operator, and if the filename does not have a "."
following it, ".MOD" will be added to the filename. If the
system can find the requested filename.extension, the "Done"
flag is made TRUE and we can test it. In this example, if
the flag is returned FALSE, we ask the operator to try again
until he finally inputs a filename that exists on the
default disk/directory.
NOW TO OPEN AN OUTPUT FILE
Once again, in line 21, we request a filename for
output anticipating the operation of the "OpenOutput" in
line 22. Line 22 waits for a keyboard input of a filename
and if the filename entered has no extension, it adds the
extension ".DOG" and attempts to open the file for writing.
When you input the filename, adding a "." to the end of the
filename will prevent the extension being added. If the
Filename.extension does not exist, it will be created for
you. If it does exist, it's contents will be erased.
It is nearly assured that the file will be created and
the "Done" flag will be supplied as TRUE, but it would be
good practice to check the flag anyway. It will be apparent
when we get to the program on printer output, that it is
impossible to open a file with certain names, one being
"PRN", because the name is reserved for printer
identification and the "Done" flag will be returned FALSE.
HOW DO I USE THE OPENED FILES?
Anytime you use this technique to open a file for
writing, any procedure from InOut will now be redirected to
that file. Anytime you use this technique to open a file
for reading, any procedure from InOut will access the file
named instead of the keyboard. In addition, the library
module named "RealInOut" will also be redirected with
"InOut". Any time you read or write, instead of using the
keyboard and monitor, the input and output files will be
used. The input and output will be the same except for
where it goes to and comes from, and it is possible to only
open one and leave the other intact. Thus input can be from
a file, and output can still go to the monitor.
When I/O is redirected, the module "Terminal" is still
available for use with the monitor and keyboard as I/O using
this module can not be redirected. The module named
Page 53
Chapter 8 - Input/Output
"Terminal" does not have the flexibility of input and output
that is found in "InOut" so it is a little more difficult to
use.
There is a major drawback when using "InOut" with the I/O
redirected. You are limited to one file for input and one
file for output at one time. Finally, this method cannot be
used to open a "fixed" or prenamed file, since it always
surveys the keyboard for the filename. It will probably
come as no surprise to you that all of these limitations
will be overcome with another method given in the next two
programs.
The program itself should be easy to follow, once you
realize that the flag named "Done" returns TRUE when a valid
character is found following a "Read", and FALSE when an
End-Of-File (EOF) is detected. The "Done" flag is set up
following each operation so its use is dictated by which
procedure was called last. The program simply copies all
characters from one file to another. When completed, the
two procedures named "CloseInput" and "CloseOutput" are
called to do just that, to close the files and once again
make the I/O available to the keyboard and monitor. In this
case, however, we immediately terminate the program without
taking advantage of the return to normal.
Compile and run this program, being careful not to give
it the name of an existing file for output, or it will
overwrite the old data in the file and copy new data into
it. That is the reason for the extension "DOG". Few people
will have a file with that extension. For input, use the
present filename (FILEIO.MOD), for output, use "STUFF",
"STUFF.", and "STUFF.STU", observing the resulting new
filename each time.
THE COMPLETE FILESYSTEM
Load and display the file named VARYFILE.MOD for an
example using the complete "FileSystem" module. As stated
earlier, Modula-2 does not have any input/output methods
defined as part of the language. This is because the I/O
available on computers is so diverse, there would be no way
of defining a method that could be used on all computers.
To eliminate the problem, Niklaus Wirth simply defined no
I/O as part of the language, but he did suggest a few
standard modules to perform the basic I/O tasks. Since they
are only suggestions, compiler writers are not constrained
to follow them, but in the interest of portability, most
will. A very limited subset of all of the procedures are
the only ones that will be used in the tutorial portion of
this course. (A few other procedures will be used in the
Page 54
Chapter 8 - Input/Output
example programs given in those chapters.) It will be up to
you to see that the procedures are in order with your
compiler, and where they differ, to modify them. A few
notes are available for your assistance in the COMPILER.DOC
file on your distribution disk for those compilers available
at the time of release of this tutorial.
BACK TO THE PROGRAM NAMED VARYFILE
This time we IMPORT several procedures from the library
module named "FileSystem" for I/O use. This time, we ask
for the input filename and store it internally in a string
variable. This implies that we can also define the filename
as a constant that is carried in the program, making it
possible to use a certain preprogrammed filename for input.
We use the procedure "Lookup" to open the file. This
procedure uses three arguments within the parentheses, the
first being the symbolic filename which is a record of
information about the file. (We will come to records later,
don't worry too much about it at this point.) The second
argument is the name of the file on disk we wish to access,
and the third argument is a boolean variable or constant.
If it is TRUE, and the file name is not found, a new file of
that name will be created. If it is FALSE, and the file is
not found, a new file will not be created, and the record
variable "InFile.res" will return the value "notdone".
(That refers to one variable named "res" which is a part of
the record "InFile".)
Note that the variable "InFile", is a record composed
of many parts, but for the immediate future we only need to
be concerned with its definition. It is defined as a
variable of type "File" which is imported from the module
named "FileSystem". Until you study the lesson in this
tutorial on records, simply copy the method used here for
file Input/Output.
Once the file is opened, you can use any of the
procedures included in the "FileSystem" module, being
careful to follow the rules given in your library
documentation. The remainder of the program should be self-
explanatory and will be left to your inspection. With this
example in hand, spend some time studying your "FileSystem"
module to become familiar with it, then compile the program
and run it to observe its operation.
NOW FOR MULTIPLE FILE OPERATIONS
Load and display the file named PRINTFLE.MOD for an
example program that uses 4 files at once, and still writes
to the monitor. This program is very similar to the last in
Page 55
Chapter 8 - Input/Output
that it opens one file for reading, but it opens three files
for writing. Each of the four files has its own identifier,
a record of type "File", and each has its own filename. The
three output files are firmly fixed to certain filenames,
rather than ask the operator for names, and the third
filename is a very special name, "PRN". This is not a file
but is the access to the printer. Anything written to this
file will go to your line printer, so you should turn your
printer on in anticipation of running it. Your compiler may
also allow a few other names such as "LPT0", "LPT1", etc,
and there may be other names reserved for serial I/O such as
to talk to a modem, a joystick, etc. You will need to
consult your compiler documentation for a complete list of
special names.
The program itself is very simple and similar to the
last one. A character is read from the input file, and
output to the three output files and to the monitor. In the
case of "CapFile", the character is capitalized before it is
output simply to indicate to you that the files are indeed
different. Study it until you understand it, then compile
and run it. Look at the contents of the new files to see if
they are correct.
MORE NEAT THINGS WE CAN DO WITH FILES
There are many more things that you can do with the
"FileSystem" module. It is possible to open a file, begin
reading until you come to a selected position, and change to
a write file to overwrite some of the data with new data.
You can write to a file, change it to a read file, reset it
to the beginning, and read the data back out. You can
rename a file, or delete it. It will be up to you to study
the documentation for your "FileSystem" module, and learn
how to use it effectively.
YOU ARE AT A SPECIAL POINT IN MODULA-2
With the completion of this chapter, you have arrived
at a very special point in your study of Modula-2. Many
people arrive at this point in a language and quit studying,
preferring to use the language in a somewhat limited sense
rather than to go on and learn the advanced topics. If your
needs are few, you can quit here also and be well assured
that you can write many programs with Modula-2. In fact
there will be very few times when you cannot do all that you
wish to do. However, if you choose to go on to the advanced
topics, you will find that some of the programming chores
will be greatly simplified.
Page 56
Chapter 8 - Input/Output
Whether you decide to go on to the advanced topics or
not, it would be wise for you to stop at this point and
begin using what you have learned to actually write some
programs for your own personal use. Everybody has need
occasionally for a program to do some sort of translation of
data in a text file for example. Write programs to do some
data shuffling from file to file changing the format in some
way. You should be able to think up several programs that
you would find useful.
Spend some time studying and running the programs in
the next chapter, then modify them to suit your needs,
building up a few utilities for your software collection.
The best way to learn to program is to program. You have
all of the tools you need to get started, so you would do
well to get started. Adding some programming experience
will be a big help if you decide to continue your study into
the advanced features of Modula-2.
Page 57