|
Designed for computer science instruction, Turing is simply the easiest, most fun, and most effective way of teaching programming concepts. |
|
Quick Links |
||
This document is structured as an index to a series of technical articles, followed by an index to Turing documentation followed by questions and answers.
To open a file in Turing, you use the open statement. This statement associates an integer variables with a file. In this way, you can have multiple files open at once, each with its own variable to refer to it. The open statement has the form:
open: fileNumber, fileName, capability {,capability}
fileNumber |
fileNumber is an integer variable declared
before the open statement. fileNumber is
assigned a value by the open statement. If the
open is unsuccessful (for example, if it couldn't
find the file to open when opening for get), then
fileNumber is assigned a value of zero or a
negative number, otherwise it is assigned a value that will
refer to the file opened. In general, the name of the
variable should in some way reflect the file being opened.
|
||||||||
fileName |
fileName is the name of the file to be opened.
If it is the actual name, then it must be enclosed in quotes like
any other string. fileName can also be a string
variable. You can specify a complete pathname with disk and
directory path in the file name. Note that under MS-DOS,
you must use a double backslash (\\) for backslash (\) in
the file name because backslash is a special character.
(See Why do I get "Illegal extended
character in string literal" in my open statement?
for more information.
|
||||||||
capability |
this is one of : read, write,
put, get,
seek or mod.
|
Here is an example program that opens the file "TEST" in the root directory of the C: drive (on an MS-DOS system) and puts the words "Hello, world" in it.
var myFile: int
open: myFile, "C:\\TEST", put
put: myFile, "Hello, World!"
Note that to put to the file (as opposed to the screen), you
add ": streamNumber" just after the put.
This tells the program to write what follows to the file
instead of the screen. You can put to the file exactly
what you would put to the screen. To do get's from a file,
you use the same method. You open the file for get and
then issue "get : streamNumber, variable, ..."
instructions which will read from the file instead of the keyboard.
When you are finished with a file, you should close it. This is
done automatically by Turing at the end of each run, but it's good
practise to close the file in your program. To close a file, you
use "close : streamNumber". At that
point, you can't access the file any further without opening the
file again.
Note that if you open a file for put or write, the
file is created if it doesn't exist and erased if it already exists.
If you wish to open the file for put or write and not
have the file erased, you must add mod to the list of
ioCapabilities. See How do I
append to a file? for more information.
var fileNumber: int
open: fileNumber, "test", put, seek, mod
seek: fileNumber, * % seek to eof
put: fileNumber, "Hello"
Note that the seek action is added to the capability list in
order to allow you to seek to the end of the file. The
mod is added in order to allow you to modify the file.
By default, when you open a file for put or write,
Turing erases the file if it already exists. Adding mod
ensures that this doesn't happen.
07 56 CD 15. Unfortunately, that sequence
of bytes can't easily be read by a human. Thus to put into a
form that humans can read, we use the ASCII equivalent of the
number. That is a string with the value "123456789". Using
ASCII, the character "1" is represented by the byte 31.
Likewise the character "2" has the value 32. Thus the
number 123,456,789 would be expressed as 31 32 33 34
35 36 37 38 39 in ASCII.
A binary file is a file that contains the binary representation
of its contents. An ASCII file is one that contains the ASCII
representation of its contents. In other words, if you did a
put : stream, 123456789, the file would
contain the bytes 31 32 33 34 35 36 37 38 39
while if you did a write: stream, 123456789,
the file would contain the bytes 07 56 CD 15. If
you attempt to type the contents of a binary file on the screen,
you get all sorts of weird characters, as the computer attempts
to display the characters have the ASCII values found in the file.
(In our example, byte 07 will be displayed as a "", byte 56 is "V",
byte CD is a "Í" and byte 15 is a "". Displaying the ASCII file
would display "123456789".)
While it might seem that binary files are much harder to use than
ASCII files (for example you can't display the contents of a file
to see if you wrote it out correctly), binary files have some very
useful properties. The main one is that each data type takes a
fixed amount of space. In ASCII, an integer could take as little
as one byte (the number "4" for example requires only one byte
to represent it, 34) to as many as 10 bytes (the number
"-123456789" takes 10 bytes to hold its ASCII representation
2D 31 32 33 34 35 36 37 38 39). A integer
expressed in binary form always takes 4 bytes, no matter
what the value. Likewise a real number always takes 8 bytes
and a string always takes the same number of bytes depending
on its declared length.
The second advantage is that binary files are faster to read and write. The computer uses the binary representations internally. When it reads or writes an ASCII file, it is required to convert from the internal binary form to the ASCII equivalent or back. When reading or writing a binary file, no such conversion is done.
You can find more information about these chapter 15 of the Turing Tutorial Guide (Random Access to Record on Disk), chapter 18 of Introduction to Programming in Turing and under open, read, write and close in the Turing Reference Manual.
Thus when typing out a binary file that contains lots of string data, you will see the data followed by junk characters that could be parts of old strings, or uninitialized values or almost anything else. When the computer reads the data file, it will know that the 0 byte signifies that the string actually ends at the right place.
seek : stream, 25
moves the file pointer to the 25th byte in the file. To move to the n-th record in a file, you need to know the record size. Then you do a:
seek : stream, (n - 1) * recordSize
Note that you use (n - 1) instead of n because the first record of the file starts at position 0 (i.e. the beginning of the file).
You can get the record size of the file in one of two ways. Either you can get Turing to tell you the record size, or you can determine the value experimentally.
To get Turing to tell you the size, you use the sizeof function. This function returns the size (in bytes) that a record (either type or variable) takes. Here is an example to find out the size of the rec record.
type rec :
record
name : string (20)
address : string (40)
age : int
salary : real
married : boolean
end record
put sizeof (rec)
To determine the value experimentally, use the following program:
type rec = record
... rest of record here ...
end record
var stream, size : int
var data : rec
open : stream, "junk", write, seek
write : stream, data
tell : stream, size
close : stream
put "Record size = ", size
This program writes a single record at the beginning of a new file
and then uses the tell statement to return the current position,
which is also the size of a single record. Note that the file is
opened for write so that you can do a binary write to the
file and for seek so that you can do a tell on the file.
get name : 24, address : 40, phone : 8, skip
After reading in the 76 characters on the line, the file pointer is probably pointing to just before the new line character. Without the skip, if the program checks for end of file, it will always return false, (since the file pointer is not pointing at the end of file), and if you do another read, the first character that will be read into the name field will be a new line, which is not what is wanted at all. By using the skip, the program will read over the newline and be pointing at the beginning of the next line.
One, when you want to delete a certain record, you can "zero" out the record in some manner. This is often accomplished by setting the key field to "empty" or something of this nature. When a record with a name field of "empty" is read the program knows that the record is no longer in use. Every so often you should go through the file to get rid of the "holes" (that is the "zeroed" out records) in the file. You do this by opening a second file and then doing a record-by-record read from the first file and write to the second file. Whenever you read a "zeroed" out record in the first file, you skip over it and don't write anything in the second file. At the end, the second file won't have any "holes" in it.
Two, if order is not important, whenever you want to delete a record in the middle of the file, you can instead copy the last record in the file over top of the record you want to delete and then "zero" out the last record. Later you can truncate the file as per How do I truncate a file.
Note in either of these methods, if you add records to the file you should write new records over "zeroed" out records and then only append to the file if there are no more "zeroed" out records. This saves disk space.
open : stream, "C:\\TEST\\TPROGS\\MYTEST.T", get
s := s (1 .. n - 1) + "x" + s (n + 1 .. *)
s := s (1 .. i - 1) + s (j + 1 .. *)
var line : string
get line : * % Read an entire line of input into line
Note that there is no way to be able to enter (for example) a
full name and an age on the same line. Turing has no way of
knowing where the full name would end and the age begin. Thus
you can either read a single token or an entire line. (You
can also read in a fixed number of characters, but that's
rarely useful in keyboard input.
var s : string := "Forward slash = / and backslash = \\"
colour (4) % The colour is set to red
put "Red"
colour (20) % The colour is set to blinking red
put "Blinking Red"
colour (12) % The colour is set to bright red
put "Red"
colour (28) % The colour is set to blinking bright red
put "Red"
setscreen ("graphics:vga")
drawfillbox (0, 0, maxx, maxy, 12) % Fill screen with bright red
colourback (5) % Set the background colour to purple
locate (10, 10)
put "Hello" .. % Puts Hello on a purple background
Note that if you have Turing 7.1 or greater, you can set another
colour to represent black using the setcolour procedure.
The other part where colour 0 is found is that whenever a put is done in graphics mode, the letters are automatically surrounded by a block in colour 0. (This is done by the IBM BIOS, so there's no easy work around.) This means that if you've done a colourback, then any text will be surrounded by the colour specified in the colourback command.
First from the DOS prompt, run PCX2TM2 file.pcx. This will display the graphics file and save it as file.tm2, which Turing can read. Then in your main program, include SCRNFL2.T and make a call to FileToScreen. FileToScreen has the following definition.
FileToScreen (x, y : int, filename : string)
You can find example programs that demonstrate this in the EXAMPLES/PCX directory that comes with Turing.
For example, a string (1) takes 2 bytes. A string (4) takes 5 bytes.
This error most often appears in conjunction with dynamic arrays of strings, or even more commonly, when declaring an array using sizepic for a takepic buffer. Try printing out the value of the sizepic call to get an idea of how large an array you're trying to declare. A full VGA screen is 150K, well over the maximum 64K for the stack.
More often, it means that the routine just called has a large number of local variables, which won't fit on the stack. Calculate the rough size of the local variables. As always, largs arrays (especially of strings) are often the culprit.
turing -stack=64
To make matters a little more complicated, the stack doesn't necessarily get set to the stack size specified. What happens is that Turing tries to allocate that amount of space. If there's not enough memory, then Turing decreases the amount asked for by 2K and then tries to allocate that. It continues to decrease it until it reaches a minimum of 10K or so. Thus it is possible to have a 10K strack, even when you've specified 64K.
You can determine how much stack was allocated to a program by selecting the Run Info menu item from the Run menu after a program has been run. The dialog box displays that maximum amount of stack it tried to allocate and the actual amount of stack that was allocated.
However, in order to make pointers easier to use, Turing conceptually structures them like arrays, except arrays where you have to allocate each element individually. While there is not enough space for a complete explanation of pointers, here's a small explained example:
var list : collection of
record
name : string
next : pointer to list
end record
var first : pointer to list
new list, first
list (first).name := "Tom"
This defines list to be a collection. Note that list does not
actually take up any memory. first is declared to be a pointer
to list, but it doesn't actually point to anything until the
next line. The new command actually creates an element of
the collection. It makes first point to the memory just
allocated. The last line shows how you assign to an element
of the collection. Notice that the collection is treated like
an array name with the pointer being an index into the array.
For more information check the Turing Reference Manual.
var printerStream : int
open : printerStream, "printer", put
put : printerStream, "This is being sent to the printer instead of the screen"
put "This is being sent to the screen and not the printer"
close : printerStream
If you are familiar with the escape sequences of your
particular printer, you can send them to the printer
by doing a put : stream, char (asciiCode) ..
to send a particular ascii code. Note that Turing
can't use characters 0 or 128, so you won't be able to send
those characters (See Are there illegal
values for character, integers and strings in Turing?).
Note that this method does not currently work for MacTuring. It does work for MacOOT.
As for strings, the hex values 0x80 and 0x00 are illegal for the same reason. You can't read in either by a getch or using the chr function a character with a value of either 0 or 128.
http://www.holtsoft.com
Technical support questions can be e-mailed to west@hsa.on.ca. Questions involving sales can directed to chris@hsa.on.ca.