TABLE OF CONTENTS
  1. PREFACE FOR THE TEACHER

    1. Document Philosophy
    2. Student Expectations
    3. Sorting and Binary Files Units
    4. How This Document is Divided
    5. Timeline Considerations
    6. Turing Stuff Resource

  2. SEQUENTIAL FILES

    1. File Creation
    2. File Reading
    3. File Modification
      1. Field content
      2. Adding records
      3. Adding fields
      4. Deleting records
      5. Deleting fields
    4. Assignments
      1. Practise Questions for Sequential Files
      2. General Quesitons for Sequential Files
    5. Suggested Project
    6. Unit Test
      1. Test
      2. Answers
    7. List of Turing Programs for Unit

  3. ARRAYS

    1. Introduction to Arrays
      1. Need for Arrays - Why Have Them?
      2. Definition
      3. Declaration
      4. Initialization
        1. init
        2. loops
    2. Array Stuff to Keep in Mind
      1. Range Specification
      2. Example Using Number File
      3. Example Using String File
    3. Related Arrays
      1. Explanation - Why Have Them?
      2. Using Related Arrays in File Manipulation
    4. Dynamic Arrays and Their Use as Parameters
      1. Explanation - Why Have Them?
      2. Bubble Sort
      3. Sorting Related Arrays
    5. Assignments - Practise Questions
    6. Suggested Project
    7. Unit Test
      1. Test
      2. Answers
    8. List of Turing Programs for Unit

  4. RECORDS

    1. Introduction to Records
      1. Need for Records - Why Have Them?
      2. Definition
      3. Declaration
      4. Initialization
    2. Sorting using Arrays of Records
    3. Assigments - Practise Questions for Records
    4. Suggested Project
    5. List of Turing Programs

  5. COMBINED PROJECT - SEQUENTIAL FILES, ARRAYS, RECORDS

  6. OVERALL TEST

  7. APPENDIX - TURING PROGRAMS


A. PREFACE TO THE TEACHER

1. Document Philosophy

This following document offers a step-by-step approach, complete with handouts, explanations and programs, for teaching the topics of sequential files, arrays and records in Turing. A concerted effort has been made to develop these topics so that one topic logically progresses to the next. If you choose to make use of this resource for teaching or learning these topics, maintaining the sequence would be advisable. If you choose to utilize only selected handouts then you may have to make minor alterations as they may refer a previous topic.

The philosophy behind this sequential approach originates in a strong belief that students, like all of us, are most receptive to learning and then applying this knowledge, when they are presented with solid reasons for doing so. In short, they must see the benefit derived in putting the required effort into the learning. This document, by presenting these units in a step-by-step approach, hopefully is consistent with this end.

2. Student Expectations

Because of the sequential nature of this document, it is necessary to outline what the students should already have been exposed to. Basically, students should be well-versed in the basics of structured programming in Turing. This would constitute familiarity with the following general topics:

The Turing Environment
Handling Output
Variables and Constants
Repetition
Selection
String Handling
Subprograms - Functions and Procedures

3. Sorting and Binary Files Units

The topic of sorting is not adequately handled in this document. Although, the bubble sort is used in the programming examples, no handouts are given to present the topic. After the students have a good working knowledge of arrays and can manipulate them proficiently, it would be timely to then present them with a unit on sorting. In this document the ideal spot to interject a topic on sorting would be after subtopic #2 in the array unit. The remainder of this document can then be tackled. Depending on the sorting algorithm you choose to accentuate, the sorting procedures may have to be altered. As mentioned, for simplicity's sake, the programs make use of the bubble sort.

I have also tried to show the connection with records and the more advanced topic, binary files. Depending on the level of programming you wish to cover in this course, you may elect to follow the records unit with the topic of binary files. In that case you may want to modify the last project so that it encompasses both sequential and binary files.

You may also want to consider elaborating on the topic of data types in the array unit by covering subrange types and two-dimenstional arrays or tables. It would certainly depend upon the ability of your students and difficulty level of your course. The keener programmers in your class should be capable of programming at this level.

4. How this document is divided

The main topics, SEQUENTIAL FILES, ARRAYS and RECORDS are presented as three separate units, that is B, C and D, respectivley. They are further divided into subtopics and sometimes sub-sub topics. The title of the subdivisions serves as a description of the topic covered. These three units can serve as handouts to the students. As each topic is covered, explanations are given and illustrative, sample programs are provided.

A listing of the programs is provided. As well, the appendix at the end of this document contains a hardcopy of each program.

5. Timeline Considerations

Suggested Time Allotments Per Topic(Approx 70 Min Periods)
File Creation And Reading 1
File Modification 2
Assignment Practice 3
Project 3
Test 1
Arrays - Introduction 2
Array Stuff To Keep In Mind 1
Related Arrays 2
Dynamic Arrays 2
Assignment Practice 3
Project 3
Test 1
Records - Introduction 1
Sorting Using Arrays Of Records 2
Assignment Practice 3
Project 3
Overall Project 5
Overall Test 1

About 7 - 8 weeks is required. If you have less time available eliminate the sub-projects. This will lessen the time by about 2 weeks.

6. Turing Stuff - Resource

There are various grade 11 handouts dealing with sequential files in the Turing Stuff binder which may expect knowledge of arrays, records and sorting. They provide excellent alternate assignments and projects. The exercises are:

GR 11 Exercises, Assignments and Projects

Arrays and Files Assignment (David Didur)
Database Management System (Joe Kolarich, Paul Keenan, Gerry Grimes)
Two Dimensional Arrays (David Didur)
Cryptoquip (Steve Richardson)
Equations in 2 Space (Arie Spiering)
Graphics and Music Project (Martha Greenbow)
Mini Database (Chris Robart)
Popular.t Project (Myra Darling)
Speed Trap (Angela Partland)
Student Marks (Sherry Mason)
Bingo (Maureen Darling)

Grade 12/OAC
Arrays: Lists (Dan Miduli)
Arrays: Tables (Dan Miduli)
Creating a Book Search Program (Dan Miduli)
Database on Discipline (Dan Miduli)
Record Structures (Dan Miduli)
Shuffling Card Game (Dan Miduli)
Two-Dimensional Arrays & Magic Square (Dan Miduli)
Using Library Files (Rob Scott)
Accounts Receivable Project (William Boston)
Application Building (Elaine Palmer)
Arrays and Sorts (Liz Mandzuk)
Blue Jays and Batting Stats (Bob Walton)
Bowling (Cindy Phair)
Citrus Sales (Dennis Lafontaine)
Creating a Database (David Sigman)
Hangman (Bill MacCallum)
Mastermind (Bill MacCallum)

B. SEQUENTIAL FILES

1. File Creation

Sequential files in Turing are text files and as such they can be created in two ways:

1) by using the editor

This method requires you to start a new file, and then simply key in the data. Save the file and your data file is created.

2) by creating a file using the open statement

Below is an example of a Turing program which creates a file. In this example our file is named, "example". Each record consists of three fields. The name is a string, the age is an integer and the income is a real.

        % This program creates a sequential file "example".
        % The file is composed of the name, age and salary for
        % an indeterminate number of people. The highlighted
        % sections are the new statements you need to learn when
        % creating sequential files in Turing.
        var stream, age : int
        var income : real
        var name : string
        open : stream, "example", put
        assert stream > 0
        loop
                put "Please enter the name of your friend or \"stop\" to quit."
                get name : *
                exit when name = "stop"
                put "Enter the age of ", name, "."
                get age
                put "Enter the income of your friend ", name, ".'"
                get income
                put : stream, name
                put : stream, age
                put : stream, income
        end loop
        close : stream

Explanation of Turing code

open : stream, "example", put

open is a Turing command which creates a connection to a file. It takes three arguments. A connection to the file is assigned via the first argument, the integer variable, stream. If the connection is successful, then stream is assigned a positive integer value. This stream value represents the number of the busline assigned for this connection. If the connection is not successful, a value of zero is assigned to the variable stream. The next argument is the name of the file requiring the connection. In this instance the file is named "example", a constant. A filename can also be in variable form, or can even specify a path and the filename. The third argument is the attribute for opening the file. In this case the attribute is put. This means that the file is to be created. Be careful when using put. If a file already exists with the name "example", this statement will erase what was in memory before.

assert stream > 0

This statement is not necessary for execution. It simply confirms that the open statement was successful. If it was successful, assert returns true and the program continues to execute. If open was unsuccessful, that is, stream has a value of zero, then the program breaks and the error message, "assert condition false", is returned. This is not a very elegant method for checking to ensure that the file opened successfully. Error trapping stream is much more effective. In the initial programs, assert will be satisfactory, but note that a more elegant method will be expected.

put : stream, name
put : stream, age
put : stream, income

These statements send information to the file "example". The stream argument means that the data is transmitted to the file via the busline assigned to "example" in the open statement. Following this argument is the data that is to be sent via the busline to the file. The data is sent in the sequence stated, that is, a string, an integer and a real. An example could be:
        name as Fred Flintstone; age as 47 and income as 23234.12.

close : stream

This statement closes the connection to the file "example".

After this program has executed, the file "example" will be in your directory. It will contain all the data that you have entered. Here is a sample of what this file may contain:

Fred Flintstone
47
23234.12
Barney Rubble
46
1123.67
Wilma Flintstone
45
11235.6
Betty Rubble
42
3425.67
Pebbles Flintstone
2
234.5
Bam-Bam Rubble
3
234.5
Mr. Slate
55
100000
Joe Rockhead
49
23412.9
Kazoo
10000
123456.87

You will notice that the data follows the sequence in the program. A name, an age and an income value appear for each record.

2. File Reading

The accessing of data from a sequential files must, as the type implies, be "sequential". In order to access the nth piece of data in a file, all previous (n-1) pieces of data must have already been accessed. In the same vein, if an item has already been accessed, the only way to reaccess it would be to close the file, reopen the file and then access all items before the data item which is required and then the item itself.

The analogy of playing a specific song from a tape is useful here. Suppose, your tape cassette, "Freddy Flintstone Sings the Blues", has eight songs on it. To listen to the fifth song, you must have already listened to the prior four songs on the cassette. Unlike this analogy, however, in order to listen to the fifth song on the cassette again, you need only rewind the portion of the tape, to the beginning of the fifth song. When reading sequential files, the only way to reread or reaccess already retrieved data is to close the file, reopen the file for reading and then reread the entire file until you re-encounter the data your wish to review.

        % This Turing program retrieves the data from the file
        % "example". It retrieves the data into the three
        % variables: name, age, and income. In essence these three
        % variables make up a complete record.

        var stream, age : int
        var income :real
        var name : string
        open : stream, "example", get
        assert stream > 0
        loop
                get : stream, skip
                exit when eof(stream)
                get : stream, name : *
                get : stream, age
                get : stream, income
                put name:30, age:10, "$",income:0:2
        end loop
        close : stream

Explanation of Turing code:

open : steam, "example", get

Like the previous explanation for the open statement, we see three arguments. The first is the integer stream. If the open statement is successful, then stream contains a positive integer. If the open statement is not successful, then the value of stream is zero. The second argument is the name of the file. In this case "example" is a constant. Variables and paths can be used as this argument. The last argument is the file attribute. In this case the file is to be opened for reading. The get attribute will allow the program to retrieve the data in the file sequentially.

assert stream > 0

As before, this statement is not necessary for execution. It simply determines whether the open statement was successful. If the open statement was successful, assert returns true and then the program continues. If it was unsuccessful, then the program breaks. As was already mentioned, this is not a very elegant method for checking to ensure open is successful. Error trapping stream is much more effective.

get : stream, skip

This statement skips over the white spaces in the file and sets the reading 'marker' or 'cursor' or 'pointer' to the beginning of the next data item to be read. White spaces in Turing include new line markers, new page markers, and so on. They do not effect the actual text or data that constitutes the file.

exit when eof (stream)

The end of a Turing file is appended by an end of file marker. This marker indicates that there is no more data to be retrieved. The above conditional statement returns true when the end of file marker is found. This indicates that there is no more data to be read from the file "example". The loop is then exited and retrieval of the data from the file stops. If the condition returns false, then the retrieval of name, age and income will continue for yet another record.

get : stream, name : *
get : stream, age
get : stream, income

These statements retrieve data from the file "example". Care is required to ensure that the items are retrieved in the same order as they were created. In this particular program, first a string, then an integer and then a real must be retrieved. The names of the variable are arbitrary. They do not need to be the same as the variables used in the creation program. The order of retrieving the variables, however, is very important. It must match the order used in the creation of the file or you may be unpleasantly surprised by the results.

This program assumes that the file has been created so that each record has three fields. If the file has not been created in this manner, then this approach will cause an end of file error. When you are unsure of the integrity of a file, precede each get of the above get statements with, "get : stream, skip", and "exit when eof(stream)" as demonstrated below.

                get : stream, skip
                exit when eof (stream)
                get : stream, name : *
                get : stream, skip
                exit when eof (stream)
                get : stream, age
                get : stream, skip
                exit when eof (stream)
                get : stream, income

This will ensure that if a record has not been created properly, then the program will not break and give an end of file error.

close : stream

This statement ends the connection to the file "example". It closes the named file.

3. File Modifying

a) Field Content Modification

Once a file has been created there will undoubtedly be occasion to make amendments to its contents. Turing makes allowances for this but the task, though simple, is a bit tedious. Because sequential files are accessed for either creating or reading (put or get) modification requires the creation of a temporary file which assists in the modification. Basically the steps are that the original file is copied into the temporary file and the copy file complete with the desired changes is written back into the original file.

To illustrate file modification, the program below will modify the data in the data file "example" so that each record will be modified. Each person is made one year older and given a raise of $5000.00.

Step One

The original file "example" will be opened with the get attribute, and the file "temp" is opened with the put attribute. This will allow for the contents of "example" to be copied into the file "temp". The result will be two identical files, one called "example" and the copy called "temp". As shown below, if Fred and Barney constitute the two records in "example", then they will also make up the two records in "temp".

example temp
Fred Flintstone Fred Flintstone
47 47
23234.12 23234.12
Barney Rubble Barney Rubble
46 46
1123.67 1123.67

Step Two

Now open "temp" with the get attribute and "example" with the put attribute. Retrieve data from "temp", make the alterations to the data that are required and then rewrite the altered data back into the original file "example". Make each person one year older and give them a raise of 5000 dollars.

  temp example
name Fred Flintstone Fred Flintstone
age 47 (+1 to age) 48
income 23234.12 (+5000 to income) 28234.12
name Barney Rubble Barney Rubble
age 46 (+1 to age) 47
income 1123.67 (+5000 to income) 6123.67


The program below illustrates the modification of the age and income field for each record in the file "example". The key field, that is field which will identify the record, will be the name field.
        % This program will modify the file "example" so that each
        % person is one year older and makes $5000.00
        % more than before.

        var stream1, stream2, age : int
        var income :real
        var name : string
        open : stream1, "example", get
        open : stream2, "temp", put
        assert stream1 > 0
        assert stream2 > 0

        % opens example and makes a copy of all data into temp
        % like Step One above

        loop
                get : stream1, skip
                exit when eof (stream1)
                get : stream1, name : *
                get : stream1, age
                get : stream1, income
                put : stream2, name
                put : stream2, age
                put : stream2, income
        end loop
        close : stream1
        close : stream2

        % at this point there are two identical files in memory,
        % "example" and "temp"
        % opens "temp" for reading and rewrites data and changes to
        % "example"
        % Like Step Two above.

        open : stream1, "temp", get
        open : stream2, "example", put
        assert stream1 > 0
        assert stream2 > 0
        loop
                get : stream1, skip
                exit when eof (stream1)
                get : stream1, name : *
                get : stream1, age
                get : stream1, income
                put : stream2, name
                put : stream2, age+1            % person one year older
                put : stream2, income+5000      % raise of $5000.00
        end loop
        close : stream1
        close : stream2 

At the end of this program, example will have been modified and "temp" will be a copy of what "example" looked like before the modifications. The user need have no knowledge of "temp" having been used at all. You can use the system commands to delete "temp" from memory if you wish. In this way no record of "temp" is left. Adding the following two lines of code to the program will delete the file "temp". A word of caution, if you run Turing on a secured network environment, this system command may not run because students may not have the access necessary to delete the file.

var success : int
system( "del temp",success)

There can be a variety of file modifications necessary. In the file "example", for instance, we may want to do the following:

1)Add records to the file
Add new characters (their name, age and income) to the file "example"

2)Add fields to each record
Give each record more information such as an address, a phone number or a fax number

3)Delete a record from the file
Get rid of one of the characters in the file

4)Delete fields from each record
Since we are in an era of equality of opportunity in the job market, we may want to, for instance, remove the age field as it may be seen as discriminatory

5)Change data within a record
As in the program above, we want to make each person one year older or give them a raise of $5000.

In each of the above cases, there are minor differences in programming code. Essentially, however, a copy must be made of the original file. The copy file along with the desired changes is then re-written into the original file.

b. Adding Records

This program below will be used to add a record (name, age and income) to the file, "example". This program appends the new record to the end of the file but alterations to the code can put the record at the beginning or between other records, as desired.

% The first step in modifying the program is to make a copy of
% the file "temp". It is an exact duplicate of "example"

proc copy
        cls
        var age, s1, s2 : int
        var name : string
        var income : real
        open : s1, "example", get
        open : s2, "temp", put
        loop
                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, age
                get : s1, income
                put : s2, name
                put : s2, age
                put : s2, income
        end loop
        close : s1
        close : s2
end copy

% This is the second step. The old records found in "temp" are
% first recopied into the file "example". A new record is
% input via the keyboard and then added to the end of the
% modified file "example".

proc addrecord

        % Makes a duplicate of the file "example" in "temp"

        copy
        var age, s1, s2 : int
        var name : string
        var income : real
        open : s1, "temp", get
        open : s2, "example", put
        loop

                % Retrieves one record from "temp"

                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, age
                get : s1, income

                % Rewrites one record into "example"

                put : s2, name
                put : s2, age
                put : s2, income
        end loop

        % Inputs from the user three fields that constitute the
        % new record

        put "Enter the name of the friend you want to add"
        get name : *
        put "Enter the age of your friend ", name, "."
        get age
        put "Enter the income of your friend ", name, "."
        get income

        % Appends new record to the end of the file "example"

        put : s2, name
        put : s2, age
        put : s2, income
        close : s2
        close : s1
        put name, " has been added to the file!"
end addrecord

% Main Program

put "This program will add a record to the file \"example\"."
add_record
put "A record has been added to the file \"example\"."

The file "example" will now have one more record then it did before the program was executed. The file "temp" will have the contents of "example" before the new record was inserted.

c. Adding Fields

This program addresses the problem of modifying a record so that additional data may be added to the file. For instance, the address of each of the people in the file may now be necessary. That means that the new data must be entered using the keyboard or read from a file. Each record will now be comprised of four fields (name, age, income and address).

% The first step in modifying is to make a copy of the
% file "temp". It is an exact duplicate of "example".

proc copy
        cls
        var age, s1, s2 : int
        var name : string
        var income : real
        open : s1, "example", get
        open : s2, "temp", put
        loop
                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, age
                get : s1, income
                put : s2, name
                put : s2, age
                put : s2, income
        end loop
        close : s1
        close : s2
end copy

% The second step is to read the current fields for each record
% from the file "temp" and then rewrite this data to the file
% "example". The information for the new field "address" is
% input through the keyboard. The program prompts the user
% for the address of each record and then adds it to the file
% "example". Each record now has four fields.

proc addfield
        copy
        var age, s1, s2 : int
        var name, address : string
        var income : real
        open : s1, "temp", get
        open : s2, "example", put
        loop
                % retrieves one record from the file "temp"
                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, age
                get : s1, income
                % Prompt to the user to enter the address via the keyboard
                put "Enter the address for ", name, "."
                get address : *
                % Writes three old fields (name, age, income) and then
                % the new field (address) to the file "example"
                put : s2, name
                put : s2, age
                put : s2, income
                put : s2, address
        end loop
        close : s2
        close : s1
        put "The file now has an address field!"
end addfield

% Main Program 

put "This program will add an address field to the file \"example\". "
put "Keyboard input is required to add an address for each record."
addfield
put "The file \"example\" now has a new address field added to each "
put "record. The fields are now name, age, income and address."

The above program has altered the file "example" so that it now contains four fields per record: a name, an age, an income and an address. Again, it is important to adhere to this order.

d. Deleting Records

We will now modify the program by deleting a complete record. The record to be deleted must be first inputted by the user. The file is scanned, record by record, until the desired record is identified. This is the record which will not be rewritten into the file. All other records are rewritten.

% The first step in modifying is to make a copy of the
% file "temp". This is true for every case of modification.
% "temp" is an exact duplicate of "example".

proc copy
        cls
        var age, s1, s2 : int
        var name : string
        var income : real
        open : s1, "example", get
        open : s2, "temp", put
        loop
                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, age
                get : s1, income
                put : s2, name
                put : s2, age
                put : s2, income
        end loop
        close : s1
        close : s2
end copy

% This program will search for the record represented by the
% variable key and it will rewrite into "example" every record
% except this key record. If the person isn't found then
% a message is sent to the user to indicate this.

proc deleterecord (key : string)
        copy
        var age, s1, s2 : int
        var name : string
        var income : real
        var found := false
        open : s1, "temp", get
        open : s2, "example", put
        loop

                %retrieves a record from "temp"

                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, age
                get : s1, income

                % if this is the record to be deleted, the boolean is true

                if key = name then
                        found := true
                else

                % if this is not the record to be deleted, rewrite it into
                % the file "example"

                        put : s2, name
                        put : s2, age
                        put : s2, income
                end if
        end loop
        close : s1
        close : s2

        % give appropriate message to the user

        if found then
                put key, " has been deleted from the file!"
        else
                put key, " is not in this file, either view file or try again!"
        end if
end deleterecord

% Main Program

var keyfield : string
var reply : string (1)
put "This program will delete a record from the file \"example\"."
put "Enter the complete name of the person whom you wish to delete from the
file."
get keyfield : *
deleterecord (keyfield)

At the end of the execution of this program, the file "example" should have one less record in it than it did before. The file "temp" will contain all the records that were in "example" before the record was deleted. Some error trapping exists. If the record was not in the file, then Turing gives the user this information. If deletion is successful, then the user is likewise informed.

e. Deleting Fields

This modification looks at the possibility that some fields in the file will no longer be needed. For instance, with all of the legitimate concern regarding equal opportunity in the job market, it may be necessary to delete the age of each person. This kind of change would require that a field be deleted. Again a similar approach is necessary. A copy of the file is made. All the wanted fields are rewritten into the original file from the copy. The unwanted field is omitted.

The program below allows the user a choice in the fields to be omitted. The field to be omitted is first identified. Again, as in all modifications, a copy of the original file is made. The copy is then used to retrieve the original data. All wanted fields are rewritten into the original file.

% This is the first step in modifying files. A copy of
% "example" is made in "temp"

proc copy
        cls
        var age, s1, s2 : int
        var name : string
        var income : real
        open : s1, "example", get
        open : s2, "temp", put
        loop
                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, age
                get : s1, income
                put : s2, name
                put : s2, age
                put : s2, income
        end loop
        close : s1
        close : s2
end copy

% This procedure receives the field to be deleted from the user.
% The entire record is retrieved from the copy and then the
% desired fields only are rewritten into the original file.

proc deletefield (option : string (1))
        copy
        var age, s1, s2 : int
        var name : string
        var income : real
        open : s1, "temp", get
        open : s2, "example", put
        loop

                % retrieves a complete record from "temp"

                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, age
                get : s1, income

                % rewrites into the original file, all fields except
                % the field to be deleted.

                if option = "1" then
                        put : s2, age
                        put : s2, income
                elsif option = "2" then
                        put : s2, name
                        put : s2, income
                else
                        put : s2, name
                        put : s2, age
                end if
        end loop
        close : s2
        close : s1

        % give user appropriate message to ensure field has been deleted

        if option = "1" then
                put "The file no longer has a name field."
        elsif option = "2" then
                put "The file no longer has an age field."
        else
                put "The file no longer has an income field."
        end if
end deletefield

% Main Program

var choice : string (1)
put "This program will delete a field from the file."
put "The user will choose a field. "
put "Choose the field you wish to alter."
put "Enter 1 to delete the field \"name\"."
put "Enter 2 to delete the field \"age\"."
put "Enter 3 to delete the field \"income\"."
loop
        getch (choice)
        exit when index ("123", choice) 0
        put "Error in input"
        put "Valid input is 1 or 2 or 3 only."
end loop
deletefield (choice)

After this program runs the file "example" will contain two fields per record while "temp" contains the original three.

4. Assignment

a. Practice Questions for Sequential Files

Little Black Book

1. Create a data file llbook which will contain the name, address, phone number, fax number and email address of your friends. Each of the above fields will be a string variable. Make your program user-friendly and use a sentinel to indicate when the user has finished entering data. Insert at least 10 records. Save this program as create.t.

2. Display all the records in your file lbbook in chart form under appropriate headings. Take care to display one screen of data at a time. Use a getch to get from one screen to another. Even if your file is not so long, you only have 10 friends, boo-hoo, your program should still include this feature to prevent names and other data from scrolling off the page. Headings should appear on each screen. Save this program as display.t.

3. Write a program to modify the file lbbook so that you can add or delete one friend at a time. Give the user a menu which includes: adding a friend to the file, deleting a friend from the file, viewing the current file and exiting the program.

     Menu
   &nbs; *****
1. Add a Record
2. Delete a Record
3. View the File
4. Exit

Error trap the menu choice. In the case of option 2, if the record to be deleted does not exist in the file, give the user a message to this effect. Save as add_del.t.

4. You decide to have two files, llbook and llbook2. The difference is that the later, llbook2 should also contain the birthday of your friends. Create this new file llbook2. Save as create2.t.

5. Create a program which uses a function to return how many friends are in your file llbook. Save as popular.t.

b. General Programs

1. Create a program which inputs the name of the file to be accessed. The program should use one function to determine whether or not the file can be opened successfully. It should use another function to determine whether or not the file is empty. Save as filechk.t. This program provides a much more elegant manner to determine if a file has opened successfully. It is much better than using assert.

2. Create a program which gives the user the following options via an error trapped menu.

Menu
*****

1. Create a file
2. Display a file
3. Display a particular record in a file
4. Exit

The first option should input a file name. The choice should be error trapped. Every record would consist of one string, one integer and one real input. Include a fourth field, a real which is the product of the second and third fields. Use any application you wish. An example could be that it is an inventory system which will input the name of the item, how many there are in stock, the cost of this item and the total value of this item in inventory.

The second option should display the contents of the entire file to the screen under appropriate headings. Prompt the user for a filename and error trap this input to ensure that the file exists and contains data. Again, the data should not scroll off the screen. Control this using a getch.

The third option should prompt the user for a filename and again this should be error trapped to ensure the file exists and has data in it. Prompt the user for the name of the item to be viewed. If the item does exist in the file, display it for the user. If the item is not found in the file, give the user an appropriate message.

The fourth option should be the only method to exit the program.

Make your program user-friendly and save as general.t.

5. Suggested Unit Project

Turing Sequential Files
Unit Project

Create a Turing program which will allow the user to create, modify, sort and display files. The program should be modular (make good use of procedures and functions) and it should be menu driven. The program begins with the following error trapped menu choices:

Menu
*****

1. Create a file
2. Add records to a file
3. Delete records to a file
4. Modify fields within a record
5. Display a record in a file
6. Display file
7. Exit program

Expectations and explanation of menu options:

1. Create file - asks for a file name, and then asks for the data in the file. Use a sentinel to indicate that the user is finished inputting data. The file should contain at least four fields with at least one of string, integer and real.

2. Add records to a file - prompts the user for a file name, prompts the user for the number of records to be added to the file and asks for the data. Error trap the file name to ensure the file exists.

3. Delete records - prompts the user for a file name, asks the user for the name of the record to be deleted and then deletes the record. Error trap the file name to ensure the file exists.

4. Modify fields within a record - prompts the user for a file name, displays the file by record and asks the user if she or he wish to change individual fields. If the user wishes to make a change, prompt the user for the new data. Again, the file name should be error trapped to ensure it exists.

5. Display a record in a file - prompts for the file name, and error traps to ensure file exists. Prompt the user for key field of record to be viewed. Display the record for the user. If the record does not exist, give an appropriate message to the user.

6. Display file - prompts for the file name, displays the file under appropriate headings with no scrolling. Use getches to get from screen to screen. Error trap the file name to ensure the file exists.

7. Exit - exits the program.

Once an option other than number 7 is chosen, and the option is executed, refresh the screen with the menu. Ensure appropriate prompting is given to the user.

You should consider including the following procedures and functions in your program. Each of the described options below, if put into a subprogram, would enhance your program and encourage modularity and organization. Carefully consider appropriate parameters.

1. Menu options and error trapping choice
2. Validate file name
3. Create file
4. Display a record from a file
5. Display file
6. Copy one file into another file.
7. Add records
8. Delete records
9. Modify fields

Suggested main program structure

Loop
        Show menu, get and error trap choice
        If selection is 1 then
                Call create
        Elsif's
        Etc..
        End if
End loop

Evaluation Used

Menu
5 4 3 2 1 0

Creation
5 4 3 2 1 0

Adding records
5 4 3 2 1 0

Deleting records
5 4 3 2 1 0

Modifying fields
5 4 3 2 1 0

Displaying record in a file
5 4 3 2 1 0

Displaying file
5 4 3 2 1 0

Exiting
5 4 3 2 1 0

Error trapping file name
5 4 3 2 1 0

Error trapping choices
5 4 3 2 1 0

Total ____________ / 50 = _____ %

6. Unit Test

a. Test

PROGRAMMING TEST
SEQUENTIAL FILES
Name ______________________
Answer all questions on the foolscap provided.
Total Marks 40

Part A
Predict the output for each of the following. Use "^" to indicate a space. (10 marks)

1. (5 marks)

        var stream : int
        var temp : string := ""
        var file : string := "tes.t"
        open : stream, file, put
        for i : 1 .. length(file)
                temp := file(i) + intstr(i)
                put : stream, temp
                put temp
        end for
        close : stream

2. (5 marks)

        var stream :int
        var word1, word2 : string
        open : stream, "test", get
        loop
                get : stream. skip
                exit when eof (stream)
                get : stream, word1:*
                get : stream, word2:*
                put word1(1), word1(*), word2(1), word2(*)
        end loop
        close : stream

        The file "test" has the following contents:
        I love computers.
        Turing has great sequential files.
        Living with Turing.
        Do you believe this file?
        Tests are fun!
        I love computers.
        Turing has great sequential files.
        Living with Turing.
        Do you believe this file?
        Tests are fun!

Part B
Draw the appropriate flowcharts for each problem listed below. (10 marks, 5 marks each)

1. The number of records in a file should be calculated and output to the screen. The file consists of records with three strings and one integer value.

2. Create a file for an indeterminant number of records. Input a sentinel for stopping the program. The file is called "test". Each record consists of four fields: first name, last name, phone number and address.

Part C
Short answer questions (8 marks)

1. Explain why two files must be opened when modifying one sequential data file. (2 marks)

2. Explain what each of the following statements accomplish in regards to sequential file management: (4 marks)
a) get : stream , skip
b) exit when eof (stream)
c) open : stream, "original", put
    open : stream, "copy", get
d) close : stream

3. Give the statements which would delete a file within a Turing program. The file is named "test.t". ( 2 marks)

Part D
Write a Turing program which will do the following. (12 marks)

Modify a file called "test" which contains an indeterminant amount of records. Each record has three fields: name, age and income. Test should add an "s" to the end of each person's name, make each person one year older and give them each a $1000 raise. In addition, it should add an address field to each record. The user should be prompted for the necessary information for each record. Display the contents of the newly modified "test" to the screen. Do not worry about scrolling or headings for your data.

Fred Flinstone Fred Flinstones
23 becomes 24
45000 46000

marks tasks
2 modify name
2 modify age
2 modify income
3 add field
3 display to screen

b. Test Answers

Part A

1. one mark per line
t1
t1e2
t1e2s3
t1e2s3.4
t1e2s3.4t5

2. one mark per line
I.T.
L.D?
T!I.
T.L.
D?T!

Part B

flowcharts - 2 at 5 marks each

Part C

1. Two files are required because a sequential file can not be opened and read from simultaneously. One temporary file will be a copy of the original. This will serve as the source document during modification. We read from the temporary file and then we rewrite the changes to the newly recreated original file. 2 marks

2.

  1. get : stream , skip - skips over white spaces in the file to the start of the next data item
  2. exit when eof (stream) - eof or end of file marker returns true if the program has reached the end of the data file. The loop which executes the retreival of data will be exited when eof(stream) is true. If eof(stream) returns false there is more data to be retrieved in the file.
  3. open : stream1, "original", put
    open : stream2, "copy", get
    The file "original" is being opened for creation and it communicates to the program via stream1. The file "copy" is being opened for retrieval and it communicates via stream2. This is used when we want to put the copy of the file back into the original file. This is used during file modification.
  4. close : stream
    This closes the connection to a file accessed by the busline number stream.
  5. var success : int
    system( "del test.t",success)

Part D

var stream1, stream2, age : int
var income : real
var name, address : string
open : stream1, "test", get
open : stream2, "temp", put
loop
        get : stream1, skip
        exit when eof (stream1)
        get : stream1, name:*
        get : stream1, age
        get : stream1, income
        put : stream2, name
        put : stream2, age
        put : stream2, income
end loop
close : stream1
close : stream2
open : stream1, "temp", get
open : stream2, "test", put
loop
        get : stream1, skip
        exit when eof (stream1)
        get : stream1, name:*
        get : stream1, age
        get : stream1, income
        put : stream2, name + "s"
        put : stream2, age + 1
        put : stream2, income + 1000
        put "please enter the address for : ", name
        get address:*
        put : stream2, address
end loop
close : stream1
close : stream2

7. List of Turing Progams

Name of Program Description
create.t assignment practice exercise #1
display.t assignment practice exercise #2
add_del.t assignment practice exercise #3
create2.t assignment practice exercise #4
popular.t assignment practice exercise #5
filechk.t assignment general exercise #1
general.t assignment general exercise #2
mainproj.t main project

** Note that files with no extension are probably sequential data files such as lbbook, lbbook2, temp, inventory

C. ARRAYS

1. Introduction to Arrays

a. Need For Arrays - Why Have Them?

Presently, every variable that is declared in Turing can contain only one data item at a time. In fact, when another data item is assigned to the variable, the piece of information that the variable previously contained will be replaced by the newly assigned data. This is called destructive input.

var name : string
name := "Fred Flintstone
put "The name is ", name, "."
name := "Barney Rubble"
put "The contents of name is ", name, "."
name := "George Jetson"
put "The contents of name is now ", name, "."

The above code demonstrates the concept of destructive input. The original contents, "Fred Flintstone", gets erased when the new value, "Barney Rubble", is assigned to the variable name. In addition, when the third change is made to the contents of name, both previous contents are gone, and the latest content, "George Jetson", will be the only available content.

Arrays provide a mechanism so that all three contents can be stored under one variable. Destructive input will no longer be the same stumbling block that it once presented to your programs. In arrays, each element or content we want to address is accessed by the name of the variable and the number of the content (subscript) we wish to address.

The need for arrays also becomes apparent when we want to organize data in a specific order, either alphabetical or numerical. Sorting data requires that the items be available in memory simultaneously so that comparisons can be made. Arrays allows this to occur.

Again, it is possible to store more than one data item into one variable by using the data structure called an array. By declaring a variable as an array, we can store as many items as we wish under the same variable name. There will be no destructive input because the item is accessed by variable name and number. This identifies precisely which of the items in that variable list we are referring to.

b. Definition of An Array

An array consists of a number of same-typed elements which can be stored and accessed via the variable name and the corresponding subscript.

c. Declaring Arrays

The following are four sample declarations. In each case 4 items of each type is being declared. The declaration must include the variable name, an integer range and a type.

var names : array 1..4 of string
4 strings accessed as names(1), names(2), names(3), names(4)

var nums : array 0..3 of int
4 integers accessed as nums(0), nums(1), nums(2), nums(3)

var realnums : array 11..14 of real
4 reals accessed by realnums(11), realnums(12), realnums(13), realnums(14)

var status : array 1..4 of boolean
4 booleans accessed by status(1), status(2), status(3), status(4)

Storing or accessing information to or from an array must include assigning to the variable name along with the subscript.

The following program declares an array of 10 integers, randomly generates numbers between 1 and 100 and stores them into the array, displays the numbers in the order in which they were generated, displays the numbers in the reverse order (last to first generated), and then calculates and displays the average of the 10 numbers. Finally it will output the contents of the fifth element in the array.

% declaring the array of 10 integers

var nums : array 1..10 of int
randomize

% randomly generating 10 numbers between 1 and 100 and
% storing them in the array

for i : 1..10
        randint (nums (i), 1, 100)
end for

% output the list from the first to tenth element. As i
% increases from 1 to 10, it serves as the subscript to
% identify which array element we want. On the first
% iteration of the counted loop, i has a value of 1 so
% nums(i) is accessing the contents of num(1), etc.

put "The list of numbers between 1 and 100 that has been generated is"
for i : 1..10
        put nums(i)
end for

% output the list from the tenth to the first element
% as i decreases from 10 to 1, it serves as the subscript
% for the variable to indicate which element of the array
% needs to be outputted

put "The list of numbers between 1 and 100 in backwards order is "
for decreasing i : 10 ..1
        put nums(i)
end for

% output the fifth element from the list

put "The fifth number to be generated was ", nums(5), "."

d. Initialization of Arrays

There are two methods of initializing a complete array. You can use the init command or you can use loops.

i. init

This command is very useful when the size of the array is small.

var nums : array 1..6 of int := init (11,12,13,14,15,16)
The above statement initializes the array nums so that nums(1) is 11, nums(2) is 12, nums(3) is 13, nums(4) is 14, nums(5) is 15 and nums(6) is 16.
var animals : array 1..3 of string:=init("piglet","bees","cats")
The above statement initializes animals(1) to "piglet",animals(2) to "bees" and animals(3) to "cats".

ii. loops

The below statements declare two arrays; names and listnum. The program then initializes the integer elements of listnum to zero and the string elements of names to blank. This could be useful when elements of an array must be used as accumulators. You can see how using init here would be very tedious.

var names : array 1..100 of string var listnum : array 1.. 100 of int for i : 1..100 listnum(i) := 0 names (i) := "" end for

2. Array Stuff to Keep in Mind

a. Range Specification

1. Limits for the range must be integer.

2. When the range is given as a variable, the value must be known before the array is declared. The following declaration is not valid because num has no value.

var num : int
var list : array 1..num of int

3. Init statements must have a constant range. Turing will give the error message that dynamic arrays can not use init. Both examples are not allowed in Turing.

%example one

var num : int
get num
var list : array 1..num of int := init(2,23,34,23)

%example two

var num : int := 5
var list : array 1..num of int := init(2,23,34,23)

4. If arrays are being read from a file, then the number of records in the file must be known before the arrays are declared. This means that the file must be opened, read and counted and then the file closed. The array can then be declared. The file is then re-opened, and the data can be read into the array.

b. Example with File of Numbers

This portion of a program assumes the existence of a sequential file called "numbers" which contains an indeterminate number of integers. The file is opened, counted and closed. The array is then declared. The file is re-opened, read into the array and closed.

var count := 0
var stream, num : int

% opens and counts the number of integers in the file

open : stream, "numbers" , get
loop
        get : stream, skip
        exit when eof(stream)
        get : stream, num
        count +=1
end loop
close : stream

% declare the array once the number of integers is known

var listnum : array 1..count of int

% reopens file and reads the numbers into the array listnum

open : stream, "numbers", get
for i : 1..count
        get : stream, numbers(i)
end loop
close : stream

% output the list of numbers to the screen

put "The original list of numbers."
for i : 1..count
        put numbers(i)
end for

c. Example With File of Strings

Here is another sample program, this time using strings. It asks the user for the number of nonsense words (concatenated upper case letters) that the computer should generate. It then declares the array to store the words, generates, stores and finally displays the silly words in various ways.

var reply : string (1)
var amount, size, letter : int

% determine size of the array

put "How many nonsense words do you want to store in the array?"
get amount

% declare the array

var list : array 1 .. amount of string

% initialize array for concatenation

for i : 1 .. amount
        list (i) := ""
end for

% fill array with concatenated letters

for i : 1 .. amount
        randint (size, 1, 10)

        % generate length for this word

        for j : 1 .. size
                randint (letter, 65, 90)

                % choose ascii for upper case

                list (i) := list (i) + chr (letter)

                % concatenate letter

        end for
end for
put "The silly words are being generated!"
put "press any key to view the silly nonsense"
getch (reply)
cls

% output the silly words to the screen in the order they were
% created

put "The nonsense words in the order generated are"
for i : 1 .. amount
        if i mod 23 = 0 then
                put "press any key to view the continue viewing nonsense"
                getch (reply)
                cls
        end if
        put list (i)
end for
put "press any key to view the nonsense words in reverse order"
getch (reply)
cls
var count := 0

put "The nonsense words in reverse order are:"

% output the silly words to the screen in reverse order

for decreasing i : amount .. 1
        count += 1
        if count mod 23 = 0 then
                put "press any key to view the nonsense words."
                getch (reply)
                cls
        end if
        put list (i)
end for

% output the silly words in the middle of the array

put "The middle word(s) in the list."
if count mod 2 = 0 then
        put "There are an even numbers of words in the list."
        put "There will be two middle words and they are :"
        put list (count div 2), " and ", list (count div 2 + 1)
else
        put "There are an odd number of words in the list."
        put "The middle word is :"
        put list (count div 2 + 1)
end if

% output the first and last words in the list

put "The first silly word is ", list(1),"."
put "The last silly word is ", list(count),"."

3. Related Arrays

a. Explanation - Why Have Them?

There are cases where arrays used in a program may be related. Look at the below example of data. Assume this data is stored in a sequential file named "cartoons".
CHARACTER TV SHOW GENDER ROLE
1 Fred Flintstone The Flintstones male lead
2 Barney Rubble The Flintstones male support
3 Wilma Flintstone The Flintstones female support
4 George Jetson The Jetsons male lead

The following code reads the above data into arrays from the file "cartoons".

var charname, showname, gender, role : array 1..4 of string
var stream : int
open : stream, "cartoons", get
for i : 1..4
        get : stream, charname(i):*
        get : stream, showname(i):*
        get : stream, gender(i):*
        get : stream, role(i):*
end for
close : stream

The first element in each of the above arrays refers to data about Fred; the second about Barney; the third about Wilma and the fourth about George. Related arrays, as the arrays above illustrate, are such that that elements in the nth position of each array, will inevitably refer to the same record.

As an example, the following code will ask the user which record they wish to view. It will then show the requested data. The variable name and subscript will address the correct element in each array.

var whichone : int
put "Which of the four records do you wish to view?"
get whichone
put "The information regarding record #",whichone,":"
put ""
put "Character Name: ",charname(whichone)
put "Show Name: ",showname(whichone)
put "Gender: ",gender(whichone)
put "Role Description: ",role(whichone)

b. Using Related Arrays in File Manipulation

The sequential data file "students" contains the following data:

5 test marks (what the each of 5 tests is marked out of)
student name
student's 5 marks in the above tests
next student name
next student's 5 marks, etc.

This program reads the student data into related arrays and then calculates the weighted and evenly weighted averages for each student. The two averages are compared and the better of the two is assigned to the student.

function recnum : int
        var count := 0
        var stream, dumnum : int
        var dumname : string

        % open file

        open : stream, "students", get

        % skip over 5 test marks

        for i : 1..5
                get : stream , dumnum
        end for
        loop
                get : stream, skip
                exit when eof (stream)

                % input name of student

                get : stream, dumname:*

                % input 5 student marks

                for i : 1..5
                        get : stream , dumnum
                end for

                % increment number of records by one

                count += 1
        end loop
        close : stream
        result count
end recnum

var num, stream, count : int

% counts the number of records in file

count := recnum
var reply : string (1)
var t1, t2, t3, t4, t5, totoftests, stream : int

% declare arrays

var student : array 1 .. num of string
var m1, m2, m3, m4, m5 : array 1 .. num of int
var evenlyweighted, weighted, assigned : array 1 .. num of real

% re-open file

open : stream, "students", get

% input 5 test marks

get : stream, t1
get : stream, t2
get : stream, t3
get : stream, t4
get : stream, t5
totoftests := t1 + t2 + t3 + t4 + t5

% input student names and marks into arrays

for i : 1.. num
        get : stream, student(i):*
        get : stream, m1(i)
        get : stream, m2(i)
        get : stream, m3(i)
        get : stream, m4(i)
        get : stream, m5(i)
end for
close : stream

% calculating two averages and store in arrays

for i : 1 .. num
        weighted (i) := (m1 (i) + m2 (i) + m3 (i) + m4 (i) + m5 (i)) /totoftests
        * 100
        evenlyweighted (i) := (m1 (i) / t1 + m2 (i) / t2 + m3 (i)/t3 + m4 (i)/
        t4 + m5 (i) / t5) / 5 * 100

        % assign better average of the two and store into array

        if weighted (i) > evenlyweighted (i) then
                assigned (i) := weighted (i)
        else
                assigned (i) := evenlyweighted (i)
        end if
end for
cls

% display student name, marks, and three averages in chart form

put "student name" : 20,
"m1 m2 m3 m4 m5 weighted evenly weighted assigned"
put "_________________", t1, "___", t2, "___", t3, "___", t4, "___", t5,
"_______________________________________"
put ""
for i : 1 .. num
        if i mod 20 = 0 then
                put "Press any key to continue"
                getch (reply)
                cls
                put "student name" : 20, "m1 m2 m3 m4 m5 weighted evenly weighted            assigned"
                put "_________________", t1, "___", t2, "___", t3, "___", t4, "___",         t5, "_______________________________________"
                put ""
        end if
        put student (i) : 14, m1 (i) : 5, m2 (i) : 5, m3 (i) : 5, m4 (i) : 5, m5
        (i) : 5, weighted (i) : 10 : 2, evenlyweighted (i) : 15 : 2,
        assigned (i) : 11 : 2
end for

4. Dynamic Arrays and Arrays as Parameters

a. Explanation - Why Have Them?

In the above program you will note that from the point in the program where arrays are declared we did not make use of subprograms. It would have been much more efficient to have a procedure to read the data into arrays and then to display the data but that would require that the arrays be used as parameters. The problem this presents is that until the program actually runs, the numbers of students in the file is unknown. This prevents the declaring of the arrays as parameters in the header of the subprograms because we do not know what the range is to be. Dynamic arrays are the solution to this predicament. We can declare the parameters with an "*" for the upper range as long as the actual size of the dynamic array is known by the time the procedure or function is called.

b. Bubble Sort

** Note ** It is not the purpose of this unit to present a package on sorting. I will assume that the students will be taught various sorting techniques. For simplicity, I will use bubble sort. The program listed below makes effective use of dynamic arrays.

% counts the records in the file

function countrec (file : string) : int
        var stream , x : int
        var howmany := 0
        open : stream, file, get
        loop
                get : stream, skip
                exit when eof (stream)
                get : stream, x : *
                howmany := howmany + 1
        end loop
        close : stream
        result howmany
end countrec

% reads into the dynamic array, "numbers", "num" integers from
% the sequential file "file". Note "numbers" must be a
% variable parameter as its value is changed in proc readlist

procedure readlist (var numbers : array 1 .. * of int, num : int, file :string)
        var stream : int
        open : stream, file, get
        for i : 1 .. num
                get : stream, numbers (i) : *
        end for
        close : stream
end readlist

% outputs the numbers in the dynamic array to screen. Note that
% numbers is a value parameter

procedure output (numbers : array 1 .. * of string, x : int)
        for i : 1 .. x
                put numbers (i), " "
        end for
end output

% sorts the data in the array numbers in ascending order
% Note that the array is a variable parameter because the
% swapping will cause the array to be changed in the proc

proc pause
        var reply : string(1)
        put "Press any key to continue"
        getch(reply)
        cls
end pause

% the bubble sort on the array numbers. Note the necessity for
% variable parametes as sorting will change the array

procedure sortlist (var numbers : array 1 .. * of string, num: int)
        for i : 1 .. num -1
                for j : 1 .. num -i
                        if numbers (j) < numbers (j + 1) then
                                var temp := numbers (j)
                                numbers (j) := numbers (j + 1)
                                numbers (j + 1) := temp
                        end if
                end for
        end for
end sortlist

% main program

var filename : string
put "please enter a filename"
get filename

% counts the numbers to determine size of the array

var count := countrec (filename)

% declares the array "list"

var list : array 1 .. count of string

% reads the numbers into the dynamic array "list"

readlist (list, count, filename)
pause

% outputs the dynamic array "list" in the order inputted

put "The original list is "
output (list, count)
pause

% sorts the dynamic array "list"

sortlist (list, count)
pause

% outputs the dynamic array "list" in sorted order

put "The original list is "
output (list, count)

c. Sorting Related Arrays

Remember the file "lbbook" which represented your sequential file of friends? The fields were: name of friend, address, fax number, phone number and email address. This program will illustrate how to read this file into the 5 required related dynamic arrays and how to sort them according to the name fields.

Look over the code for this program and note the following:
a) how the arrays are sent as parameters - either variable (reading and sorting) or value (displaying),
b) how the arrays whether they be value or variable parameters, are nonetheless dynamic, and
c) how many lines of swapping are required for sorting. As one of the related fields is swapped so must all the other fields. For example suppose the following represented two records in your file:

Fred Flintstone
23 Rocky Road
123-4567
123@tvland.com
678-3456

Barney Rubble
26 Rocky Road
765-4321
321@7654.ca
234-7890

When the names of Fred and Barney are compared, Barney will be swapped with Fred. If we stop here then the other related fields will be with the wrong person. Fred's address, phone, fax and email will be Barney's and vise versa. It is therefore necessary to swap all related fields. Whew!! A sorted array of the positions of records would help this but there is a better way, record structures. We will soon deal with that topic! For now, use cut and paste!!

proc menu (var opt : string (1))
        put " MENU"
        put " ****"
        put " 1. READ A FILE "
        put " 2. SORT A FILE "
        put " 3. VIEW A FILE"
        put " 4. EXIT"
        loop
                put "Make a selection 1-4 from above"
                getch (opt)
                exit when index ("1 2 3 4", opt) > 0
                put "Error in input, try again please!"
        end loop
end menu

% counts the number of records in the file to determine the size
% of the arrays

function recnum : int
        var count := 0
        var stream : int
        var dummy : string
        open : stream, "lbbook", get
        loop
                get : stream, skip
                exit when eof (stream)
                count+=1
                for i : 1 .. 5
                        get : stream, dummy : *
                end for
        end loop
        close : stream
        result count
end recnum

% sorts the data in the dynamic arrays according to name
% note the use of variable parameters. Bubble sort is used.

proc sortfile (var name, address, phone, fax, email : array 1..*
of string, n : int)
        var temp : string
        for i : 1 .. n
                for j : 1 .. n -i

                        % does this record need to be swapped?

                        if name (j) > name (j + 1) then

                                % swap the elements in name

                                temp := name (j)
                                name (j) := name (j + 1)
                                name (j + 1) := temp

                                % swap all related arrays, 3 lines per item

                                temp := address (j)
                                address (j) := address (j + 1)
                                address (j + 1) := temp
                                temp := phone (j)
                                phone (j) := phone (j + 1)
                                phone (j + 1) := temp
                                temp := fax (j)
                                fax (j) := fax (j + 1)
                                fax (j + 1) := temp
                                temp := email (j)
                                email (j) := email (j + 1)
                                email (j + 1) := temp
                        end if
                end for
        end for
end sortfile

% display the dynamic arrays. Note they are value parameters.

proc viewfile (name, address, phone, fax, email : array 1..* of string, n : int)
        var stream : int
        var reply : string (1)
        put "NAME ADDRESS PHONE FAX EMAIL"
        for count : 1 .. n
                if count mod 20 = 0 then
                        put "Press any key to continue"
                        getch (reply)
                        cls
                        put "NAME ADDRESS PHONE FAX EMAIL"
                end if
                put name (count) : 14, address (count) : 21, phone (count) : 10, fax
                (count) : 10, email (count)
        end for
end viewfile

% Read the data into dynamic arrays. Note the necessity for
% variable parameters

proc readfile (var name, address, phone, fax, email : array 1 .. * of
string, n : int)
        var stream : int
        open : stream, "lbbook", get
        for i : 1 .. n
                get : stream, name (i) : *
                get : stream, address (i) : *
                get : stream, phone (i) : *
                get : stream, fax (i) : *
                get : stream, email (i) : *
        end for
        close : stream
end readfile

% Main Program

var choice, stall : string (1)
var num := recnum
var names, address, phone, fax, email : array 1 .. num of string
loop
        menu (choice)
        put ""
        put "Press any key to continue"
        getch (stall)
        cls
        if choice = "1" then

                % silly option to read a file, just to show how to do it

                readfile (names, address, phone, fax, email, num)
                put "The file has been read!"
        elsif choice = "2" then

                % option to sort files. Readfile is included to ensure
                % that the file is opened and read into arrays. As
                % well, viewfile is called to display the sorted arrays

                readfile (names, address, phone, fax, email, num)
                sortfile (names, address, phone, fax, email, num)
                put "This is the sorted file"
                viewfile (names, address, phone, fax, email, num)
        elsif choice = "3" then

                % option to view the file. Readfile is included to
                % ensure that the file is opened and read into arrays.

                readfile (names, address, phone, fax, email, num)
                viewfile (names, address, phone, fax, email, num)
        else
                exit
        end if
        put "Press any key to continue"
        getch (stall)
        cls
end loop

5. Assignments - Practise Questions for Arrays

Use the array structure to write the following Turing programs.

1. Create a program which prompts the user for a student's name and their mark in a test which is marked out of 67. Use a sentinel to determine the end of input. Output the marks in chart form (Name and Mark) in the order input as a percent. Sort the data in descending order according to marks and redisplay the sorted list in chart form. Save as array#1.t.

2. Write a program which inputs a number of names in any order. Use a sentinel to stop user input. Ouput to the screen the names in alphabetical order so that there are no duplicate names output. At the end of the program output the names of the duplicates. Save as array#2.t.

3. Prompt the user for the number of integers they want to generate. Randomly generate the numbers, sort them in ascending order and then output the median. If the amount of numbers in the array is odd, there is a single median value. If the amount of numbers in the array is even, there are two median values. When there is an even amount of numbers, output the average of these two numbers. Save as array#3.t. The following is an example of the handling of an odd and even amount of numbers:

List : 2, 6, 7, 9, 10 (5 numbers - odd)
Median : 7
List : 5, 6, 7, 8, 9, 10 (6 numbers - even)
Median: 7.5 from (7+8)/2

4. Randomly generate 20 integers between the range 1 and 1000. Sort the numbers and then output for each number the following in chart form under appropriate headings:
Number Square Root Square Cube
9 3 81 729

Save as array#4.t.

5. Input text from the user until a sentinel indicates end of input. After the user indicates that there is no more input, clear the screen and redisplay the input so that the originial word is in one column, vowels are in another column and consonants are in the last column. Save as array#5.t.

6. Suggested Project

PROJECT
ARRAYS

There are two questions in this assignment. You should not only concentrate on completing the task so that the required output is created, but take care to program with efficiency and modularity in mind. Remember that this unit has its emphasis on arrays and that these programs are best handled using arrays effectively.

Problem #1

Old MacDonald

Initialize two arrays, animals and sounds, so that they contain the animals and their corresponding sounds, as can be heard on "Old MacDonald's Farm".

Animals Sounds
pig oink
horse neigh
dog bow
etc.

Output the song, "Old MacDonald Had A Farm", to the screen in the following way:

1. Once verse at a time, with a getch between verses.

2. The animals and sounds should be preceded by the appropriate "a" or "an", as required. This will change the initialization lines of the arrays so make sure you do not assume, as in the list above, that only "oink" will require "an".

3. Take care to prevent scolling of the song on the screen. You should provide for a verse possibly taking up more than one screen of output. If more than one screen is required, use a getch so the user can proceed when ready.

4. Output for the above would look like:

Old MacDonald Had A Farm - verse #1
************************

Old MacDonald had a farm, e-i-e-i-o
And on the farm he had a pig, e-i-e-i-o
With an oink-oink here, and an oink-oink there
Here an oink, there an oink, everywhere an oink-oink
Old MacDonald had a farm, e-e-i-o.

(getch)

Old MacDonald Had A Farm - verse #2
************************

Old MacDonald had a farm, e-i-e-i-o
And on the farm he had a horse, e-i-e-i-o
With a neigh-neigh here, and a neigh-neigh there
Here a neigh, there a neigh, everywhere a neigh-neigh
With an oink-oink here, and an oink-oink there
Here an oink, there an oink, everywhere an oink-oink
Old MacDonald had a farm, e-e-i-o.

(getch)

Old MacDonald Had A Farm - verse #3
************************

Old MacDonald had a farm, e-i-e-i-o
And on the farm he had a dog, e-i-e-i-o
With a bow-bow here, and a bow-bow there
Here a bow, there a bow, everywhere a bow-bow
With a neigh-neigh here, and a neigh-neigh there
Here a neigh, there a neigh, everywhere a neigh-neigh
With an oink-oink here, and an oink-oink there
Here an oink, there an oink, everywhere an oink-oink
Old MacDonald had a farm, e-e-i-o.

Save as oldmac.t.

Problem #2

Ask the user for the number of numbers you want to generate. Error trap this number to ensure that it is an integer value. Generate the numbers and then with getches inbetween display the following:
a) the original list with no scrolling
getch
b) the sorted list
getch
c) the mean, median and mode

Mean - average of the numbers

Median - middle value in the sorted list of numbers. If the list has an odd number of elements, the median is only one value. For example in a list of 15 numbers, the eighth element is the median. When the list has an even number of numbers, display the average of the two middle numbers. For example in a list of 10 numbers the median would be the average of the fifth and sixth numbers.

Mode - displays the number or numbers which occur most often. View the following example lists and their mode(s).

List Mode(s)
1,2,2,3,4,5,6 2
13,13,20,20,25,25,25,26,26,26 25,26
1,2,3,4,5,6 1,2,3,4,5,6

There is no need to repeat the program after one execution. Save as mmm.t.

Evaluation Scheme
Name ______________________
total mark ( _____ / 70 = _____ % )

Old MacDonald ( ____ / 30)

a and an handling
5 4 3 2 1 0

correct output
10 9 8 7 6 5 4 3 2 1 0

scrolling control and other getches
5 4 3 2 1 0

efficiency of array usage
10 9 8 7 6 5 4 3 2 1 0

Mean, Median, Mode ( ____ / 40)

input # of numbers and error trap
5 4 3 2 1 0

display original list - no scrolling and getch
4 3 2 1 0

sort list
4 3 2 1 0

display sorted list - no scrolling and getch
4 3 2 1 0

calculating and displaying mean
5 4 3 2 1 0

calculating and displaying median
8 7 6 5 4 3 2 1 0

calculating and displaying mode(s)
10 9 8 7 6 5 4 3 2 1 0

7. Unit Test

a. Test

PROGRAMMING TEST
ARRAYS, FILES, SORTING

_____ /50 marks = __________ %

NAME ________________

Part A Predict the output for each of the statements. Show the output in the space provided and mark all spaces with a " ^ ".
(10 marks)

1. 3 marks

var x : array 1..6 of string
x(1) := "1"
for i : 2 .. 6
        x(i):= intstr(i)+x(i-1)
end for
for i : 1 .. 3
        put x(i)," ",x(i+3)
end for

2. 4 marks

var name : array 1 .. 4 of string:=init ("Flintstone, F.",
Flintstone, W.","Rubble, B.", "Rubble, B.")
for i : 1..3
        for j : 1..4-i
                if name(j)>name(j+1) then
                        var temp:=name(j)
                        name(j):=name(j+1)
                        name(j+1):=temp
                end if
        end for
end for
for i : 1..4
        put name(i)(1..index(name(i),",")
end for

3. 3 marks

var nums : array 1 .. 10 := init (1,2,2,3,4,5,6,7,8,10)
var ten:=10
put "Median: ",(nums(ten div 2) + nums(ten div 2 + 1))/2
put "Median: ",nums((ten div 2) + (ten div 2 ))/2
put "Median: ",nums(ten div 2 +1) + (ten div 2)

Part B Draw flowcharts for each of the problems outlined below. (10 marks, 5 marks each)

1. Prompt the user the number of integers that a user would like to be generated and then output the original list and output the number in the middle of the list.

2. Prompt the user for 10 first and last names. Concatenate each first and last name into one variable as illustrated below and then store it into one array element. Here is an example:

input first name as "fred"
input last name as "flintstone"
store in array as "flintstone, fred"

Output the list in alphabetically descending order.

Part C (30 marks)

1. Write a Turing program that would do the following.
a) Read a file named "dst", which would have an indeterminant number of records. This means that you must count the number of records first. The file is to be stored or read into related arrays. The fields for each record are:

   first name of the student - string
   last name of the student - string
   3 marks for first 3 tests - real ( out of 100 )
   3 marks for first 3 projects - real ( out of 100 )

b) Calculate the final average mark for each student in this manner. The three tests constitute 70% of the overall mark and the 3 projects make up 30%. Store this calculation in an array. Sort according to descending order. Output the student's first and last names, the test component out of 70%, the project component out of 30% and the overall average to the screen in chart form. You do not need to worry about lining up the chart headings with their corresponding data but you must make sure to display one full screen at a time. Do not allow the data to scroll past the user. (And you thought I didn't have a heart!)

mark allocation (30)
opening file & counting records (4)
declaration of arrays (4)
inputting data into array (4)
calculating test component (3)
calculating project component (3)
storing averages into array (3)
sorting data (5)
output to screen (4)

b. Answers

Part A -10 marks
predicting output -one mark per line

1.

1^654321
21^7654321
321^87654321

2.

Rubble,
Rubble,
Flintstone,
Flintstone,

3.

Median:^4.5
Median:^5
Median:^10

Part B -10 marks
flowcharts -5 marks each

Part C - 30 marks

fcn count : int
        var tot := 0
        var stream : int
        var dummy : string
        open : stream, "dst", get
        loop
                get : stream, skip
                exit when eof (stream)
                for i : 1 .. 8
                        get : stream, dummy : *
                end for
                tot += 1
        end loop
        close : stream
        result tot
end count

proc readarray (var a, b : array 1 .. * of string, var t1, t2, t3, p1,
p2,p3 : array 1 .. * of int, var ta, pa, av : array 1 .. * of real, num: int)
        var stream : int
        open : stream, "dst", get
        for i : 1 .. num
                get : stream, a (i) : *
                get : stream, b (i) : *
                get : stream, t1 (i)
                get : stream, t2 (i)
                get : stream, t3 (i)
                get : stream, p1 (i)
                get : stream, p2 (i)
                get : stream, p3 (i)
                ta (i) := (t1 (i) + t2 (i) + t3 (i)) / 300 * 70
                pa (i) := (p1 (i) + p2 (i) + p3 (i)) / 300 * 30
                av (i) := ta (i) + pa (i)
        end for
        close : stream
end readarray

proc sort (var a, b : array 1 .. * of string, var t1, t2, t3, p1, p2,p3
: array 1 .. * of int, var ta, pa, av : array 1 .. * of real, num : int)
        for i : 1 .. num -1
                for j : 1 .. num -i
                        if av (j) < av (j + 1) then
                                var temp := av (j)
                                av (j) := av (j + 1)
                                av (j + 1) := temp
                                temp := pa (j)
                                pa (j) := pa (j + 1)
                                pa (j + 1) := temp
                                temp := ta (j)
                                ta (j) := ta (j + 1)
                                ta (j + 1) := temp
                                var temp2 := t1 (j)
                                t1 (j) := t1 (j + 1)
                                t1 (j + 1) := temp2
                                temp2 := t2 (j)
                                t2 (j) := t2 (j + 1)
                                t2 (j + 1) := temp2
                                temp2 := t3 (j)
                                t3 (j) := t3 (j + 1)
                                t3 (j + 1) := temp2
                                temp2 := p1 (j)
                                p1 (j) := p1 (j + 1)
                                p1 (j + 1) := temp2
                                temp2 := p2 (j)
                                p2 (j) := p2 (j + 1)
                                p2 (j + 1) := temp2
                                temp2 := p3 (j)
                                p3 (j) := p3 (j + 1)
                                p3 (j + 1) := temp2
                                var temp3 := a (j)
                                a (j) := a (j + 1)
                                a (j + 1) := temp3
                                temp3 := b (j)
                                b (j) := b (j + 1)
                                b (j + 1) := temp3
                        end if
                end for
        end for
end sort

proc display (a, b : array 1 .. * of string, c, d, e : array 1 .. * of real, num : int)
        cls
        put ""
        put"First Name Last Name tests(70%) projects(30%) total(100%)"
        for i : 1 .. num
                if i mod 20 = 0 then
                        var reply : string (1)
                        put "Press any key to continue"
                        getch (reply)
                        cls
                        put "First Name Last Name tests(70%) projects(30%)                                 total(100%)"
                end if
                put a (i) : 15, b (i) : 15, c (i) : 10 : 2, d (i) : 17 : 2, e (i) :
                12 : 2
        end for
end display

% program main

var numrec := count
put count
var first, last : array 1 .. count of string
var t1, t2, t3, p1, p2, p3 : array 1 .. count of int
var t, p, a : array 1 .. count of real
readarray (first, last, t1, t2, t3, p1, p2, p3, t, p, a, count)
sort (first, last, t1, t2, t3, p1, p2, p3, t, p, a, count)
display (first, last, t, p, a, count)

7. List of Turing Programs

program description
arr_test.t test question
array#1.t assignment question #1
array#2.t assignment question #2
array#3.t assignment question #3
array#4.t assignment question #4
array#5.t assignment question #5
oldmac.t suggested project question #1
mmm.t suggested project question #2
marks.t illustrate related lists and sorting
cartoon.t illustrate related lists and sorting

NOTE *** Any Turing files with no extension are sequential files such as animate, dst and students.

D. RECORDS

1. Introduction to the Record Structure

a. Need for Records - Why Have Them?

One of the best reasons to use records is that records group related arrays into one data structure. In the file that we have been using "lbbook" which contains the name, address, phone, fax and email of all your friends, related arrays were declared. Recall that in related arrays the nth element in each separate related array refers to information about the same record or in this case, the same friend. When we were sorting the arrays, we were required to swap each array to prevent the corruption of our data. Remember the example where Fred gets swapped with Barney in the array "name". We had to ensure that all of Fred's data, which were contained in the other four related arrays, were also swapped. This means we were entering 15 lines of code, 3 per item swapped. If records were used, we would just require 3 lines because the record is swapped in its entirety. As well as decreasing the necessary sorting code, records ensure that you do not forget to swap any of the related arrays as they are already a single unit.

There is another terrific reason to use a record structure but it only becomes obvious when you begin using binary files. Binary files write and read a record structure in one fell swoop. This would mean that in the above example, if it were a binary file, one statement would be sufficient to write or read the entire record. More importantly, it allows random access in binary files. You can seek to any given position within the file and access the record of the choice. This is because when a record is read or written to a binary file, it occupies a constant calculatable memory block. This record size can be used to calculate the exact position of any record in the file. This is an advanced topic and it is beyond the scope of this unit. However, the advantage of using record structures in binary files is worth mentioning.

Unfortunately, unlike binary files, sequential files require that the get and put statements access record structures field-by-field. This requires the same care when dealing with records as with related arrays. Keyboard input using get and put must also be addressed by field. The advantages of swapping a record in one step and of having the record logically grouped as one unit is still a substantial advantage that records have over related data fields. This is sufficient reason to implement records.

b. Definition of Record Data Type

A record data type is a data type that permits a group of items of possibly different types to be grouped together as a unit and thus be manipulated as a unit.

c. Declaration of Record

The following examples will show various record declarations.

% example one

var friend: record name : string address : string phone : string fax : string email : string end record

The above declaration defines the record "friend". This record contains 5 string fields: name, address, phone, fax and email. If one field needs to be addressed, then the format is:

friend.name := "Fred Flintstone"

To output this data to the screen we would use:

put friend.name

% example two

var employee:
        record
                name : string
                address : string
                weekhrs : real
                rateofpay : real
                taxcode : int
                full : boolean
        end record

The above declaration defines the record "employee" which contains 6 fields of different variable types. They include: name, address, hours worked per week, the rate of pay, a number to reference tax deduction and true or false to determine if they are full or part time workers. A sample initialization for the above record could be:

employee.name := "Fred Flintstone"
employee.address := "23 Rocky Road"
employee.weekhrs := 40.5
employee.rateofpay := 15.78
employee.taxcode := 4
employee.full := true

A sample piece of code to illustrate manipulating this record would be:

if employee.full then
        put employee.name, " is a full time employee."
else
        put employee.name, " is a part time employee."
end if

c. Declaring Arrays of Records

The declarations thus far do not handle the need presented when a program requires the sorting of data. Recall that in order to sort, the data must be in memory simultaneously and this requires data to be stored in arrays. The next set of examples illustrates how to declare arrays of records.

The first step is to use the type statement to create a record type. Once that is completed an array of that type can be declared. Using the same records as illustrated above, we will create the types required and then declare the array for each record type.

% creates the record type friendtype as per above example one type friendtype: record name : string address : string phone : string fax : string email : string end record % declares an array of friendtype var myfriends : array 1..100 of friendtype % creates the record type employeetype as per above example two type employeetype: record name : string address : string weekhrs : real rateofpay : real taxcode : int full : boolean end record % declares an array of employeetype var staff : array 1..50 of employeetype

2. Sorting Arrays of Records

The program below assumes that a file exists in memory. The fields are: a character name for a cartoon, the network the show is found on, the name of the show that the cartoon character belongs to and the year that the show started on television. The fields are four strings and an integer.

The program below illustrates how this file can be read into an array of records. The record type is "CartoonType". As in all previous cases we must count the number of records in the file before the array can be declared. To count the records we must open the file, and extract each record and increment the counter by one. We then close the connection to the file.

Once the number of records is known, the array of records can be declared. The file is then read into the array of records. Note that in sequential files the retrieval of data must be field-by-field.

The program then displays the data in chart form to the screen. When outputting to the screen, field-by-field retrieval is again the method that must be used.

The program then goes on to sort the array of records according to the name of the cartoon character. This illustrates the significant advantage of having the data in an array of records rather than in many related arrays. The selection is based on a particular field but the swap includes the entire record. The sorted list is then re-output to the screen.

% type declaration for a record type named CartoonType
% it contains 5 fields as listed below

type CartoonType :
        record
                charname : string
                network : string
                rating : string
                showname : string
                startyr : int
        end record
procedure pause
        var reply : string (1)
        locate (23, 1)
        put "Press any key to clear the screen and continue."
        getch (reply)
        cls
end pause

% prompts the user for a filename and ensures it exists

proc getfilename (var file : string)
        var stream : int
        loop
                put "Please enter the name of the cartoon file you wish to access."
                get file
                open : stream, file, get
                exit when stream > 0
                put "Sorry this file does not exist, try again"
                pause
        end loop
end getfilename

% counts the number of records in the file
% note that the retrieval, even if the record structure is used,
% must be field by field in a sequential file

function countrec (file : string) : int
        var num := 0
        var stream : int
        var cartoon : CartoonType
        open : stream, file, get
        loop
                get : stream, skip
                exit when eof (stream)
                get : stream, cartoon.charname : *
                get : stream, cartoon.network : *
                get : stream, cartoon.rating : *
                get : stream, cartoon.showname : *
                get : stream, cartoon.startyr
                num += 1
        end loop
        close : stream
        result num
end countrec

% reads the data into the array of records, cartoon. Note
% that the array is a variable parameter and that
% the retrieval in a sequential file is field by field

proc readrecords (file : string, var cartoon : array 1 .. * of CartoonType,
num : int)
        var stream : int
        open : stream, file, get
        for i : 1 .. num
                get : stream, cartoon (i).charname : *
                get : stream, cartoon (i).network : *
                get : stream, cartoon (i).rating : *
                get : stream, cartoon (i).showname : *
                get : stream, cartoon (i).startyr
        end for
        close : stream
end readrecords

% Again, get and put must access record structures
% field-by-field. This uses the array of records, cartoon as a
% value parameter

proc view_records (cartoon : array 1 .. * of CartoonType, num : int)
        put "CARTOON CHARACTER NETWORK RATING NAME OF SHOW YEAR CREATED"
        put ""
        for i : 1 .. num
                if i mod 20 = 0 then
                        pause
                        put "CARTOON CHARACTER NETWORK RATING NAME OF SHOW YEAR                            CREATED"
                        put ""
                end if
                put cartoon (i).charname : 23, cartoon (i).network : 9,                             cartoon(i).rating :5, cartoon (i).showname : 30, cartoon (i).startyr
        end for
end viewrecords

% sorts the array of records cartoon according to the field
% char_name. Note that the record structure comes in handy
% when sorting for the record is swapped in its entirety.
% This makes records worthwhile

proc sortrecords (var cartoon : array 1 .. * of CartoonType, num : int)
        for i : 1 .. num -1
                for j : 1 .. num -i
                        if cartoon (j).charname > cartoon (j + 1).charname then
                                var temp := cartoon (j)
                                cartoon (j) := cartoon (j + 1)
                                cartoon (j + 1) := temp
                        end if
                end for
        end for
end sortrecords

% Main Program

var file : string

% ask user for legitimate filename

getfilename (file)

% count number of records in the file

var numrecords := countrec (file)

% declare the array of records

var cartoonlist : array 1 .. numrecords of CartoonType

% read records in file into the array of records

readrecords (file, cartoonlist, numrecords)
put "The records as per listed in the file ", file, "."
put ""

% display contents of the array of records in chart form

viewrecords (cartoonlist, numrecords)
pause

% sort the array of record according to cartoon name and
% then display the contents of the sorted array to the screen

sortrecords (cartoonlist, numrecords)
put "The cartoons sorted by ascending first name."
put ""
viewrecords (cartoonlist, numrecords)

3. Practice Assignment Questions

Write Turing programs which will do the following:

1. Define a record structure appropriate for collecting data for an athletic league whether it be CFL, AFL, NHL, NBA etc. It could even be for a league you find yourself a member of. The record structure should include data for players in the paricular league you have chosen:
player name
current team
position
salary
age
rating (1 to 10 with 10 is best rating and 1 is the worst)
Write a procedure to read the data from a sequential file named "sports". Save as record#1.t.

2. Write subprograms for #1 which will enable you to sort the data according to any field the user chooses: player name, current team, position, salary, age or rating. Add to the first program and save as record#2.t.

3. Write the subprograms to display #1 or #2 to the screen under appropriate headings with no scrolling. Add to the second program and save as record#3.t.

4. Modify the program "cartoon.t" which is in this package. Currently there are five fields: the name of the character, the network on which the cartoon is shown, the rating, the name of the cartooon show and the year the cartoon came into existence. Add the search feature to the program. Using either the name of the cartoon character or the nane of the show the character appears, do a search for the particular data. If no match is found, communicate this to the user. Save as record#4.t.

4. Suggested Project

Cards

Making use of the record structure, create a program which will do the following.

1. Present the following options to the user via a menu.

Menu

1. Shuffle and Deal Out Cards
If user selects this option, the deck is recreated and shuffled so that it is ready to be dealt. The deck is then dealt out to the four players.

2. Play the Game
This can only be done if the cards have been dealt. Display the winner per game and the on-going score for each of the four players. A win is awarded if the player is the only one with the highest card. If there is a tie, no one gets the point. At the end of the thirteen hands, a winner or winners is/are declared. There is no graphics component but some graphics would certainly enhance the mark.

At the end of a game, re-start the initializing of the deck. The user must again shuffle the deck and deal before the subsequent game is played.

3. Quit
This should be the only way to exit the program.

Evaluation
Name _________________________
Total Marks ____ / 60 = ____ / 100

assign cards to record
10 9 8 7 6 5 4 3 2 1 0

shuffle the dec
10 9 8 7 6 5 4 3 2 1 0

deal the hands
10 9 8 7 6 5 4 3 2 1 0

hand by hand playing and assigning of winner
10 9 8 7 6 5 4 3 2 1 0

overall winner
10 9 8 7 6 5 4 3 2 1 0

ease of play for user
10 9 8 7 6 5 4 3 2 1 0

5. List of Turing Programs

program description
record#1.t assignment exercise #1
record#2.t assignment exercise #2
record#3.t assignment exercise #3
record#4.t assignment exercise #4
cartoon.t required for amending question #4
rec_proj.t project question

Note *** - Turing files without extensions such as animate and sports are sequential files

E. COMBINED MAJOR PROJECT - SEQUENTIAL FILES, ARRAYS AND RECORDS

MAJOR PROJECT - SEQUENTIAL FILES, ARRAYS AND RECORDS DATABASE PROJECT - MY COLLECTION

Program Description

You will be required to create a program for data manipulation. The data that you manipulate will be of your choice. A good suggestion would be that it would be something that appeals to you and that you could make use of. For instance, if you are a collector, perhaps a database to handle your collection would be useful. It will be tedious to work on something that is not of use. Even if you do not have a personal need for this database, creating one for someone else would give a meaningful purpose to your project.

Decide what fields are necessary in your database and create the appropriate record structure for these fields. A menu driven approach would be most suitable.

Your program must allow the user to:

a) Create and modify the database. The modifications must be such that the number of fields in the record structure would not be altered. These other file modifications must be available: adding records, deleting records and modifying existing fields.

If problems arise during the modification process keep the user informed. For example:

Also make the user aware of successful operations. For example:

b) Search the database by important fields. You decide which fields are important. Ask if you are unsure. For instance, if your database deals with stamp collection, perhaps viewing stamps worth over a given price, viewing the origin country of stamps or the age of stamps would be suitable search options. The user should be informed if the query has failed and when possible given the reason. For example:

c) Display the database by individual record or file (chart form)

d) Sort the database according to important fields. Again the importance of a field is up to your discretion.

e) Provide adequate error trapping. Take precaution will all interaction to ensure that the input does not crash your program or create unsuspected results.

It is assumed that your program will run!!!

Evaluation of Collection Project
TOTAL MARKS _____ / 100

Name_________________________
appropriateness of plan and design of database
10 9 8 7 6 5 4 3 2 1 0

error trapping
10 9 8 7 6 5 4 3 2 1 0

modularity and efficiency in program structure
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

creation and updating of database
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

searching database by important fields
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

sorting database by important fields
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

displaying file and individual records
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

F. OVERALL TEST

1. Test

TEST
SEQUENTIAL FILES, ARRAYS AND RECORDS

total marks ______ / = _____ %

NAME ________________________________

Place answers on the foolscap provided.

PART A Predict the output for each of the following Turing programs. Use "^" to indicate a space. 16 MARKS - 1 each line

1.

% assume keyboard input is "p", then "y", then "y"
        var cartoon :
                record
                        sing, dance, act : boolean
                        salary : real
                end record
        var ans : string (1)
        var sum := 0
        put "Can you sing?(y/n)"
        getch (ans)
        put ""
        if ans = "y" then
                cartoon.sing := true
                sum += 1
        else
                cartoon.sing := false
        end if
        put "Can you dance?(y/n)"
        getch (ans)
        put ""
        if ans = "y" then
                cartoon.dance := true
                sum += 1
        else
                cartoon.dance := false
        end if
        put "Can you act?(y/n)"
        getch (ans)
        put ""
        if ans = "y" then
                cartoon.act := true
                sum += 1
        else

                cartoon.act := false
        end if
        cartoon.salary := sum * 10000
        put "Your salary is $", cartoon.salary : 0 : 2, "."

2.

        var word := "array_files_record"
        var a : array 1 .. 4 of string := init ("a", "b", "c", "d")
        for i : 1 .. 4
                a (i):=a(i) + word(i*2) + word(index (word,"_")..*)
                put a (i)
        end for

3.

        var word2 := "Turing is great!"
        var eachone:array 1..length(word2) of string(1)
        for decreasing i:length(word2) ..1
                eachone(i) := word2(i)
        end for
        for i: 1..length(word2) div 3
                put eachone((i-1)*3+1):2,eachone((i-1)*3+2):2,
                eachone((i-1)*3+3):2
        end for

PART B - Draw flowcharts for each of the following problems - 15 marks, 5 marks each

1. Create a file called "TEST" with the following fields: student name, array test mark, files test mark, and overall test mark. The name is a string and the three test marks are integer values. Prompt the user for this information and use a sentinel to determine when there is no more input.

2. Read the above file "TEST". Output the average for each student. Output all data read and calculated in chart form.

3. Output the middle letter of the middle name in the file "TEST".

PART C - Short answer questions. (10 marks)

1. Define each of the following and provide a few lines of Turing to illustrate each: (4 marks)
a) init
b) record type
c) array of records
d) dynamic array

2. What is the advantage of using an array of records over related arrays? Provide a concrete example. (3 marks)

3. We have studied that modifying files requires the use of an extra temporary file which contains a copy of the original file data. Explain how using arrays could replace the second. (3 marks)

PART D - TURING PROGRAM - 19 marks

The following code constitutes the type definition and main program of a Turing file.

% type definition

type numType :
        record
                num : int
                square, cube, squareroot, cuberoot : real
                isprime : boolean
        end record

%main program

var num : int
var word : string
inputnum (word, num)
var numbers : array 1 .. num of numType
assignnums (numbers, num)
sortnums (numbers, num)
printnums (numbers, num)

Create all the necessary subprogams to complete this program. Do not make changes to the main program. The following is a description of the purpose of each subprogram.

inputnum - prompts the user for a number. The number has no restrictions except that it must be an integer. This subprogram must ensure that the input is a valid integer. If it is not, the user will continue to be prompted until the input is correct.

assignnums - randomly generates a number between 1 and 100.

Assigns this number to the field num. Finds the square, cube, square root and cube root of this number and then assigns each to the respective fields. It also determines whether the number is prime or not. If it is prime, the field contains true. If it is false, the field contains false. This is repeated for all the numbers generated and they must be stored in the array of records "numbers".

sortnums - sorts the array of records according to number in your choice of ascending or descending order.

printnums - outputs the contents of the array of records "numbers" in chart form. Uses a getch to move from screen to screen if the output exceeds one screen length.
inputnum 4 marks
assignnums 6 marks
sortnums 5 marks
printnums 4 marks
total 19 marks

2. Answers

PART A -PREDICTING OUTPUT 1 mark per line (16 marks)

1.
Can^you^sing?(y/n)
p
Can^you^dance?(y/n)
y
Can^you^act?(y/n)
y
Your^salary^is^$30000.00.

2.
ar_files_record
ba_files_record
c__files_record
di_files_record

3.
T^u^r^
i^n^g^
^^i^s^
^^g^r^
e^a^t^

PART B - FLOWCHARTS - 15 marks - 5 each

PART C - SHORT ANSWER - 10 marks as outlined in test

1a. init - a statement used in Turing to initialize an array. The bounds of the array must be constants.

var friends:array 1..4 of string := init ("Fred", "Barney", "Wilma",
"Betty")

1b. Record type - a type declaration of a set of fields which can be of various types grouped as one data structure and treated as one unit.

type RecordType:
        record
                name:string
                address:string
                age:int
        end record

1c. Array of records - an array declaration of a programmed defined record type.

type RecordType:
        record
                name:string
                address:string
                age:int
        end record
var people : array 1 .. 3 of RecordType

1d. Dynamic array - The size of an array is dependent on data which is known at least just before the dyamic array is used. It is useful when using arrays as subprogram parameters

proc generatenum ( var a : array 1..* of int, n:int)
        % contents of procedure
end generatenum

%main program

var n:int
put "How many numbers?"
get n
var numbers : array 1..n of int
generatenum(list,n)

2. The advantage of using an array of records over a group of related arrays is that the record structure makes the fields one data unit in memory. It minimizes the chance of forgetting to assign to a field. The greatest benefit is when sorting. Regardless of the number of fields, comparisons can be done by a field and the record can be swapped as a whole. (3 lines complete a swap of n fields, n*3 lines required for related arrays swapping)

3. The file can be opened counted and closed. The arrays can be declared. The file is re-opened and read into the arrays. The original data and the changes can then be re-written into the file. The array serves as a holding tank for the original data eliminating the need for the second file.

PART D - TURING PROGRAM - 19 marks as outlined in test

type numType :
        record
                num : int
                square, cube, squareroot, cuberoot : real
                isprime : boolean
        end record

function primenum (n : int) : boolean
        var count := 0
        for i : 1 .. n
                if 1 mod n = 0 then
                        count += 1
                end if
        end for
        if count > 2 then
                result false
        else
                result true
        end if
end primenum

function square (n : int) : real
        result n ** 2
end square

function cube (n : int) : real
        result n ** 3
end cube

function squareroot (n : int) : real
        result n ** (1 / 2)
end squareroot

function cuberoot (n : int) : real
        result n ** (1 / 3)
end cuberoot

proc inputnum (var word : string, var n : int)
        loop
                var stat := true
                put "How many numbers would you like to generate?"
                get word
                for i : 1 .. length (word)
                        if index ("0123456789", word (i)) = 0 then
                                stat := false
                                exit
                        end if
                end for
                exit when stat
                put "Wrong input, try a number"
        end loop
        n := strint (word)
end inputnum

proc assignnums (var nums : array 1 .. * of numType, n : int)
        randomize
        for i : 1 .. n
                randint (nums (i).num, 1, 100)
                nums (i).square := square (nums (i).num)
                nums (i).cube := cube (nums (i).num)
                nums (i).squareroot := squareroot (nums (i).num)
                nums (i).cuberoot := cuberoot (nums (i).num)
                nums (i).isprime := primenum (nums (i).num)
        end for
end assignnums

proc sortnums (var nums : array 1 .. * of numType, n : int)
        for i : 1 .. n -1
                for j : 1 .. n -i
                        if nums (j).num > nums (j + 1).num then
                                var temp := nums (j)
                                nums (j) := nums (j + 1)
                                nums (j + 1) := temp
                        end if
                end for
        end for
end sortnums

proc printnums (nums : array 1 .. * of numType, n : int)
        var reply : string (1)
        for i : 1 .. n
                if i mod 20 = 0 then
                        put "press any key to see next screen"
                        getch (reply)
                        cls
                end if
                put nums (i).num : 6, nums (i).square : 10, nums (i).cube : 10,                     nums(i).square_root
                : 20 : 2, nums (i).cube_root : 20 : 2
        end for
end printnums

% main program

var num : int
var word : string
inputnum (word, num)
var numbers : array 1 .. num of numType
assignnums (numbers, num)
sortnums (numbers, num)
printnums (numbers, num)

G. APPENDIX - PRINTOUTS OF TURING PROGRAMS

% add_del.t - sequential assignment question # 3
proc menu (var opt : string (1))
        put " MENU"
        put " ****"
        put " 1. ADD A RECORD "
        put " 2. DELETE A RECORD"
        put " 3. VIEW A FILE"
        put " 4. EXIT"
        loop
                put "Make a selection 1-4 from above"
                getch (opt)
                exit when index ("1 2 3 4", opt) > 0
                put "Error in input, try again please!"
        end loop
end menu
proc copy
        var s1, s2 : int
        var name, address, phone, fax, email : string
        open : s1, "lbbook", get
        open : s2, "temp", put
        loop
                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, address : *
                get : s1, phone : *
                get : s1, fax : *
                get : s1, email : *
                put : s2, name
                put : s2, address
                put : s2, phone
                put : s2, fax
                put : s2, email
        end loop
        close : s1
        close : s2
end copy
proc add_record
        copy
        var s1, s2 : int
        var name, address, phone, fax, email : string
        open : s1, "temp", get
        open : s2, "lbbook", put
        loop
                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, address : *
                get : s1, phone : *
                get : s1, fax : *
                get : s1, email : *
                put : s2, name
                put : s2, address
                put : s2, phone
                put : s2, fax
                put : s2, email
        end loop
        put "Enter the name of the friend you want to add"
        get name : *
        put "Enter the address of your friend ", name, "."
        get address : *
        put "Enter the phone number for your friend ", name, "."
        get phone : *
        put "Enter the fax number for your friend ", name, "."
        get fax : *
        put "Enter the email address of your friend ", name, "."
        get email : *
        put : s2, name
        put : s2, address
        put : s2, phone
        put : s2, fax
        put : s2, email
        close : s2
        close : s1
        put name, " has been added to the file!"
end add_record
proc del_record
        copy
        var s1, s2 : int
        var name, address, phone, fax, email, key : string
        var found := false
        open : s1, "temp", get
        open : s2, "lbbook", put
        put "Enter the name of person whom you want to delete from the file"
        get key : *
        loop
                get : s1, skip
                exit when eof (s1)
                get : s1, name : *
                get : s1, address : *
                get : s1, phone : *
                get : s1, fax : *
                get : s1, email : *
                if name = key then
                        found := true
                else
                        put : s2, name
                        put : s2, address
                        put : s2, phone
                        put : s2, fax
                        put : s2, email

                end if
        end loop
        close : s2
        close : s1
        if found then
                put key, " has been successfully deleted from the file!"
        else
                put key, " could not be found in the file. Deletion aborted."
        end if
end del_record
proc view_file
        var stream : int
        var count := 0
        var reply : string (1)
        var name, address, phone, fax, email : string
        open : stream, "lbbook", get
        put "NAME ADDRESS PHONE FAX EMAIL"
        loop
                get : stream, skip
                exit when eof (stream)
                count += 1
                get : stream, name : *
                get : stream, address : *
                get : stream, phone : *
                get : stream, fax : *
                get : stream, email : *
                if count mod 20 = 0 then
                        put "Press any key to continue"
                        getch (reply)
                        cls
                        put "NAME ADDRESS PHONE FAX EMAIL"
                end if
                put name : 14, address : 21, phone : 10, fax : 10, email
        end loop
        close : stream
end view_file
% main program
var choice, stall : string (1)
loop
        menu (choice)
        put ""
        put "Press any key to continue"
        getch (stall)
        cls
        if choice = "1" then
                add_record
        elsif choice = "2" then
                del_record
        elsif choice = "3" then
                view_file
        else
                exit
        end if
        put "Press any key to continue"
        getch (stall)
        cls
end loop

% file animate - text file (animate)

Fred Flintstone
ABC
G
The Flintstones
1967
Wilma Flintstone
ABC
G
The Flintstones
1967
Barney Rubble
ABC
G
The Flintstones
1967
Betty Rubble
ABC
G
The Flintstones
1967
George Jetson
ABC
G
The Jetsons
1970
Jane Jetson
ABC
G
The Jetsons
1970
Judy Jetson
ABC
G
The Jetsons
1970
Elroy Jetson
ABC
G
The Jetsons
1970
Scooby-Do
NBC
G
The Adventures of Scooby-Do
1974
Scrappy
NBC
G
The Adventures of Scooby-Do
1974

% array test solution - part D - Turing program (arr_test.t)

fcn count : int
        var tot := 0
        var stream : int
        var dummy : string
        open : stream, "dst", get
        loop
                get : stream, skip
                exit when eof (stream)
                for i : 1 .. 8
                        get : stream, dummy : *
                end for
                tot += 1
        end loop
        close : stream
        result tot
end count
proc read_array (var a, b : array 1 .. * of string, var t1, t2, t3, p1, p2,p3 : array 1 .. * of int, var ta, pa, av : array 1 .. * of real, num: int)
        var stream : int
        open : stream, "dst", get
        for i : 1 .. num
                get : stream, a (i) : *
                get : stream, b (i) : *
                get : stream, t1 (i)
                get : stream, t2 (i)
                get : stream, t3 (i)
                get : stream, p1 (i)
                get : stream, p2 (i)
                get : stream, p3 (i)
                ta (i) := (t1 (i) + t2 (i) + t3 (i)) / 300 * 70
                pa (i) := (p1 (i) + p2 (i) + p3 (i)) / 300 * 30
                av (i) := ta (i) + pa (i)
        end for
        close : stream
end read_array
proc sort (var a, b : array 1 .. * of string, var t1, t2, t3, p1, p2,
p3 : array 1 .. * of int, var ta, pa, av : array 1 .. * of real, num : int)
        for i : 1 .. num -1
                for j : 1 .. num -i
                        if av (j) < av (j + 1) then
                                var temp := av (j)
                                av (j) := av (j + 1)
                                av (j + 1) := temp
                                temp := pa (j)
                                pa (j) := pa (j + 1)
                                pa (j + 1) := temp
                                temp := ta (j)
                                ta (j) := ta (j + 1)
                                ta (j + 1) := temp
                                var temp2 := t1 (j)
                                t1 (j) := t1 (j + 1)
                                t1 (j + 1) := temp2
                                temp2 := t2 (j)
                                t2 (j) := t2 (j + 1)
                                t2 (j + 1) := temp2
                                temp2 := t3 (j)
                                t3 (j) := t3 (j + 1)
                                t3 (j + 1) := temp2
                                temp2 := p1 (j)
                                p1 (j) := p1 (j + 1)
                                p1 (j + 1) := temp2
                                temp2 := p2 (j)
                                p2 (j) := p2 (j + 1)
                                p2 (j + 1) := temp2
                                temp2 := p3 (j)
                                p3 (j) := p3 (j + 1)
                                p3 (j + 1) := temp2
                                var temp3 := a (j)
                                a (j) := a (j + 1)
                                a (j + 1) := temp3
                                temp3 := b (j)
                                b (j) := b (j + 1)
                                b (j + 1) := temp3
                        end if
                end for
        end for
end sort
proc display (a, b : array 1 .. * of string, c, d, e : array 1 .. *
of real, num : int)
        cls
        put ""
        put "First Name Last Name tests(70%) projects(30%) total(100%)"
        for i : 1 .. num
                if i mod 20 = 0 then
                        var reply : string (1)
                        put "Press any key to continue"
                        getch (reply)
                        cls
                        put "First Name Last Name tests(70%) projects(30%)                                 total(100%)"
                end if
                put a (i) : 15, b (i) : 15, c (i) : 10 : 2, d (i) : 17 : 2, e (i) :          12 : 2
        end for
end display

% program main

var num