
See also our notes on Programming and Software Development in Higher Still Computing.
This article is intended to offer help in developing UniCOMAL programming courseware for the above unit. It refers to the national unit specification document "Computer Programming (Higher), First edition, May 1997". This forms part of the document "Arrangements for Computing" which is available from:
Higher Still Development Unit
Scottish CCC
PO Box 12754
Holyrood Road
Edinburgh EH8 8ZA
and may also be downloaded from the Higher Still website: http://www.higher-still.org.uk. Page numbers refer to the section entitled "National Unit Specification - Computer Programming (Higher)."
This will eventually become quite a long article and will be periodically updated over the period June-September 1998. The views expressed in this article are those of the author alone and have no official status. The article is in the public domain: any teachers or students wishing to make use of some or all of this material in courseware are most welcome to do so.
Click here for the Alphabetic Index to this article.
There are five stipulated outcomes (the suggested time allocations are given on p.14):
The following sections try to offer help for the UniCOMAL user on selected points from the outcomes, especially where the arrangements document seems unclear or vague.
The performance criteria refer to:
"Written or oral" evidence is required, as usual, and should specifically cover dry run, trace tables and break points in debugging; explanation of how software can be efficient in its use of memory and processor time; and insert, delete and replace operations in list processing. No specific evidence requirement, except that all classes in the range must be covered, is given for the use of editors. On p.7, however, it is stated that "it would be highly desirable for students to experience the use of debugging and editing tools ... A range of features, such as find and search and replace, which are used in program editors could also be examined using practical examples."
This outcome requires the student to explain features of a software development environment. The specified features are "data structures" and "file handling". The student must define the feature correctly, explain its purpose correctly, and correctly explain its means of implementation in the software development environment under study.
The evidence requirements further indicate that, so far as data structures are concerned, "written or oral" evidence should cover two-dimensional arrays, records, queues and stacks (page 3): and for file handling, the support notes indicate that file creation, file operations and sequential file access should be covered. The student will not have to implement all of these, but will have to provide evidence of awareness of the means of implementation. The support notes suggest that "The student is expected to explain in some detail the purposes of features, with illustrative examples of when their use is appropriate", (Page 9), and "It would be beneficial to learning if students could compare implementations of features in different software development environments" (Page 10).
A stack is a LIFO (last in first out) structure in memory. It is fundamental to the operation of all computer programs, because (for example) it is used to store temporarily the address from which a subroutine was called, so that when a program has completed the work of a subroutine, it can resume work at the point from which the subroutine was called, by reading the return address from the stack. High-level language programs always assume (a)that a stack is available, and (b) that the programmer wants the language translator to handle all the work involved in using it.
A stack is "managed" by a single pointer, which points to the next free location at the top of the stack. (Compare this with a queue, which needs two pointers, one for the head and one for the tail of the queue). The value of this pointer is updated by either of two operations, "push", which adds an item to the top of the stack, and increments the pointer accordingly, and "pop" (or "pull") which copies the item from the top of the stack and decrements the pointer. ("Pop" does not actually remove the top data item from the stack, but because the stack pointer has gone down by 1, the item below now becomes the top item and the item which has been "popped" is forgotten.) A static stack occupies a fixed, limited area of memory, whereas a dynamic stack can grow and shrink freely in memory as required.
It is, of course, possible to write your own high-level stack structure. There is an excellent example of a recursive stack in UniCOMAL in Dick Klingens' Recursion Tutorial, Chapter 5, "Data Structures". This implements a dynamic stack using pointer variables in UniCOMAL, and is very like such implementations in the C language, although rather easier to read and understand. It is, however, recursive, and this, together with its use of pointers, would seem to put it outwith the scope of the Higher Level Programming Unit, and push it well into Advanced Higher territory.
A much simpler example, simulating a static stack using an integer array, is included in the queue.zip file in the downloads directory. This file also contains a simple queue simulation.
The UniCOMAL reference manual discusses arrays (and string lengths, STRUCs and pointers) in the section on the DIM command, pages 190-198. String and numeric arrays of up to 31 dimensions (!) can be set up. For example, two-dimensional arrays can be set up as follows:
The array (a) above might be being used to store the names of the pieces on individual squares of a chess board, (b) might be used to record the identifying numbers of the racing cars at the start of a Grand Prix race, and (c) might be a table of height measurements used in surveying an area of ground. Here is a short program which uses array (a) above to lay out a chess board:
Notice particularly the use of nested loops to manipulate the indices of the array.
Finding student-accessible examples of the use of two-dimensional arrays is quite difficult. Fifth year seems a little too early to start talking about matrix manipulation.
UniCOMAL does not have a keyword RECORD, such as you find in Pascal. Instead, the programmer can use the STRUC keyword to build a user-defined data structure. STRUCs are quite well described in the Reference manual, Appendix H (Structures), page 493. The first example given shows how to build a simple record to store a person's name, address and age using a STRUC:
The next step is to declare either variables, or arrays of variables, of this structure:
Notice the dot notation used for STRUC variables. It differes slightly from the $ suffix for strings and the # suffix for integers, in that we have to write:
The individual fields making up a record are accessed by naming them following the dot:
We can print out the entire contents of a list of structured variables very quickly:
A very useful example of the use of STRUCs as records, involving also a binary search routine, is given in the Reference Manual P 497. An efficient program occupies the smallest possible amount of memory and takes the smallest possible number of processor operations to complete its task. This sounds fairly straightforward, but is complicated by many other considerations. The need for tight and efficient programming, so as to reduce to a minimum the demands made on the computer by the program, has been greatly reduced in recent years by the rapid advances in both memory capacity and processor speed. The modern software industry seems to pay relatively little attention to efficiency as a desirable aspect of its products.
The support notes (p. 7) state that the student should be able to explain memory efficiency in relation to the scale of the program - the program should not require memory resources disproportionate to its scale, and similarly processor efficiency - algorithms should not use processor time disproportionate to their function.
When considering memory efficiency, it is important to remember that there may be more than just the "visible" part of the program present in the computer's memory while the program is being executed. In the case of an interpreted UniCOMAL program, the source code must be present in memory, and so also must the UniCOMAL interpreter and any external modules which are used by the program, such as the system module, the graphics module and so on. In the case of a compiled UniCOMAL program, a run-time version of the interpreter, and run-time versions of any required modules, are linked with the source code during compiling to produce a stand-alone version of the program, which will run without needing the interpreter.
For compiled languages such as C and Pascal, the compiled machine-code is linked with machine-code libraries to give a stand-alone machine code program. This is present in the memory along with any dynamically-linked libraries (DLLs) which are needed by the machine-code.
As an example, we could look at the "Hello World!" program so often used to demonstrate that a programming language is working properly. It's task is to display the text "Hello World!" on the monitor of the computer it is running in, or, in a WIMP system, to display that text in a program window. This table shows examples of the memory used up by the "Hello World!" program in a range of programming languages:
On the face of it, the AcornSOFT COMAL version of Hello World! is nearly 20 times more memory efficient than the Delphi version! This is misleading, of course, because the Delphi version does a lot of work in opening and maintaining a window in a graphical user interface, none of which is needed by the Acorn COMAL version. Having said that, the Acorn COMAL interpreter (16K of hand-built 6502 machine-code) is an amazingly memory-efficient language translator within its limits. There has been much criticism of programs produced by "Visual" software development systems such as Delphi and Visual BASIC, in that the applications produced by them are much larger than they need be - they are sometimes referred to as "bloatware".
Processor efficiency is also a fairly complicated idea. Generally speaking, interpreted languages such as UniCOMAL are very inefficient in their use of processor time compared with compiled languages such as C, Delphi and Pascal. This is because, during program execution, the processor has to shuttle back and forward through the translator program for each line of the source program, before executing that line and then stepping on to the next. In a compiled program, all the translation has already been done during the compiling stage, so the processor need not waste operations during execution.
Modern compilers perform optimization on the source code while it is being converted into machine code. This process can "tailor" the machine code to suit the particular processor for which it is being compiled, and can either produce a compact, memory-efficient machine code program, or a fast, processor-efficient program which will probably require more memory. Usually, an optimizing compiler is forced to compromise between memory efficiency and processor efficiency, and the trade-off can often be controlled to some extent by the programmer by choosing suitable compiler options before compiling the source code.
It is interesting to note that compiled UniCOMAL programs, although fairly memory-efficient compared to their interpreted versions, are no more processor-efficient than they were before compiling. This is because the compiler does not attempt to produce a machine-code version of the source code, but instead bundles a run-time copy of the interpreter with the source code so as to produce a stand-alone program. School students, perhaps because they don't often produce very long programs, rarely make full use of the facilities of the UniCOMAL Editor, which are described in pages 78 to 83 of the UniCOMAL reference manual. The following items are taken from those pages and from the descriptions of the LIST, RENUM and AUTO commands:
AUTO starts automatic line numbering. AUTO 100,10 starts at line 100 and goes up in steps of 10
LIST lists the source code.
RENUM Renumbers program lines. As usual, it can be used as in
In addition, when using UniCOMAL in MS-Windows, it is possible to open more than one window on the same program, and thus to place different sections of the code side-by-side for comparison and editing. See the notes on MS-Windows.
It is possible to edit a UniCOMAL program in an ordinary text editor, such as Windows Notepad. To do this, first prepare an ASCII version of the program, without line numbers, using the DISPLAY command:
DISPLAY "program.txt
The resulting file can be dragged into Notepad and edited there. Of course, you lose the on-entry syntax checking and the case insensitivity, but you gain the search facility of Notepad. Having finished Editing, the file can be dropped back into the UniCOMAL window, where it will be SCANned automatically. See the notes on MS-Windows.
No matter how careful you are when you write program code, your programs are likely to have errors, or bugs, that prevent them from running the way you intended. Debugging is the process of locating and fixing errors in your programs, and programs to help you do this are called "debuggers".
The amount of debugging help provided with a program language varies widely from language to language. Interpreted languages, such as BASIC and COMAL, are executed line-by-line from the source code. This means that errors will usually stop the program at, or near, the statement which caused the error, and allow you to examine the code straight away so as to find the error quickly. Because of this, they often don't need separate debugger modules. UniCOMAL, for example, doesn't have one.
Compiled languages, on the other hand, are executed from the object code, which you can think of as a block of machine code which has been produced from the source code by the compiler. At run time, the source code is no longer available to use for tracking down bugs! So the first duty of a debugger utility is to build a map of links between the object code and the source code so as to allow you to find out which statement in the source code caused the problem in the object code when it was run. This is quite a difficult task, and slows the compiler down a lot, so it is often provided as an option which you can select at compile time if you think you're going to need it. As we saw earlier, this task is not needed in an interpreted language.
A trace table is a table used to record changes to the values of variables during the progress of a program. Trace tables can be prepared by hand during desk-checking or dry-running. A trace table is prepared by listing all the variables used in the program in columns of the table. The rows of the table simulate the execution of a statement in the program. Actual results, indicated by the values of the variables in the trace table, are compared with pre-calculated expected results. The differences will reveal any flaws in the logic of the algorithm.
A debugger module for a compiled program maintains an electronic trace table in the computer's memory, so as to link the variables used by the programmer in the source code with the values stored in memory by the machine-code version of the program. In this way, the programmer can get tracing information from the debugger when a logic error is encountered on running the compiled code. With an interpreted language, such as UniCOMAL, this is not needed, since the variables themselves are still available for inspection when the program is run. It is, however, useful to be able to check the execution path through the program up to the point at which an error is encountered, and this is provided in UniCOMAL by the TRACE command.
Syntax errors are simple mistakes in "putting together" program statements, like "PTINT 54.3" instead of "PRINT 54.3" for example. Modern program languages detect these errors before the program is compiled or interpreted, by putting the statements through a syntax checker at a very early stage, often while the code is being typed in. UniCOMAL's syntax checker is second to none in its ability to detect mistakes on entry.
Programs aren't always typed in by hand, however. Often the source code for a program is loaded into the computer from an outside source. In this case, the correctness of the syntax has to be checked before either interpreting or compiling the code, and a syntax checker is often provided as a separate module. In UniCOMAL, the SCAN command is used for this purpose. When you type SCAN, the source code is checked line-by-line and any syntax errors or structure errors (such as opening a loop with FOR and forgetting to close it again with ENDFOR) are reported. You can't use an external module in an UniCOMAL program unless you have SCANned it first to make sure its syntax is correct.
Run-time errors occur when your program contains valid statements, but the statements cause errors when they are executed. For example, your program might try to open a nonexistent file, or it might try to divide a number by zero. The operating system detects run-time errors and stops program execution when they occur.
Many run-time errors cannot be anticipated by the programmer. For example, the programmer cannot tell in advance when the user is going to forget to switch the printer on! So errors of this sort should be handled in such a way as to avoid the program crashing. This is particularly important in programming for a multi-tasking environment, for if a program crashes when it is interacting with other programs on the same processor, it may well pull the operating system down along with it. One way to cope with the unexpected is to use an "exception handler" facility, which could be thought of as part of the overall debugging facilities of the language. In UniCOMAL, this is provided by the TRAP .. HANDLER .. ENDTRAP structure.
Using a debugger, you can run to a specific program location. From there, you can execute your program one statement at a time, watching the behavior of your program with each step. When you execute the statement that causes your program to fail, you can fix the source code and then carry on testing.
Logic errors occur when your program statements are valid, but the actions they perform are not the actions you intended. For example, logic errors occur when variables contain the wrong values, when graphic images are the wrong shape, or when the output of the program is wrong in some way.
Logic errors are often difficult to find because they can show up in unexpected places. You need to thoroughly test your program to ensure that it works as designed. A debugger can help you locate logic errors by displaying the values of variables etc. as your program executes.
You frequently need to examine the values of variables and expressions to uncover bugs in your program. For example, it is helpful to know the value of the index variable as you step though a for loop, or the values of the parameters passed to a function call. These values are displayed by a TRACE facility, usually provided as part of a debugger, and helped along by a FIND facility, which lets you locate the positions of variables in the program or in its modules. In a compiled language, the debugger module maintains a trace table in memory which links source-code variables to machine-code values.
The TRACE command is provided in UniCOMAL for this purpose. When you type TRACE after a program has halted due to error, the UniCOMAL interpreter lists, backwards, the stages of the program's execution which led to the unhappy event. TRACE can sometimes produce a very long listing, so it is possible to divert its output to a file instead of to the screen.
FIND is used in UniCOMAL to locate the positions of variables in the program. It is particularly valuable in debugging long programs.
Breakpoints pause program execution during a debugging session at places that you specify in the source code.
You can set breakpoints into your source code at positions before potential problem areas, then run your program. Your program will pause when it encounters a breakpoint, and display the line containing the breakpoint. You can then use the debugger to view the state of your program, or to step over or trace into your code one line at a time.
UniCOMAL provides the commands STOP and CON to permit breakpoints to be set. When the STOP command is encoutered in a program, the program stops (reasonably enough!) and allows the programmer to examine the values of variables and so on. Then the CON command can be used to resume execution at the point at which it was stopped. There is little precise detail about these four algorithms given in the statement of standards for outcome 1, except the evidence requirement "written or diagrammatic evidence that the student has designed and described the algorithms detailed in performance criterion (d) for all classes in the range." In the "guidance on content" section, p. 7, the arrangements further state that "list operations include inserting, deleting and appending items in lists", and, later on "the comparison of internal sorting algorithms would illustrate efficiency of memory usage and processing time".
That gives a total of seven algorithms to be covered, (frequency count, binary search, internal sort 1, internal sort 2, insert in list, delete from list and append to list) from which the student would require to provide evidence of designing and describing four. In outcome 3, the student is required to provide evidence of implementation of four of these. There is a very neat example of the use of a binary search in the UniCOMAL reference manual, Appendix H ("Structures"), pp. 497 - 498. This example uses a UniCOMAL STRUC to store a warehouse stock record, then searches a small database of these records using a binary search. In outcome 2 of the unit (see p. 8), the student is required to give comprehensive definitions of various data structures, including records, so this example is doubly appropriate. The arrangements document does not go into any detail about the required "Frequency Count" algorithm. "Frequency count" could mean: in increasing complexity of algorithm. Here is an algorithm for the simplest case:
Here is a UniCOMAL function, based on this algorithm, to work out the number of occurrences of a given letter in a text file:
This function could be called from a simple main program like this:
and gives a single line of output like this:
assuming that the file 'frequent.txt' were present in the same directory as the program.
So far, so good. But what if we want a table showing the frequences of all the letters of the alphabet in that text file? We could simply loop round the letters 'a' to 'z', using the 'letter_frequency' function, like this:
This program will work, and produce output like this:
and the output could be altered to generate a table of values rather than 26 separate lines as shown.
Doing it that way is very processor-inefficient, however. For each letter of the alphabet, the program has to process the entire text file, one character at a time, in order to count the letter's frequency. We can write a different algorithm, using an array to hold the letter frequencies, which will allow us to generate the same result in only one pass through the file:
In UniCOMAL, for the letter-frequency exercise, that would look like this:
This program gives exactly the same results as 'letter frequency 2', but just over 27 times more quickly. It is much more processor-efficient than 'letter frequency 2', but rather less memory-efficient, since it needs memory space for the array of frequencies, whereas 'letter frequency 2' did not. A queue is a FIFO (first-in first-out) data structure used to sequence multiple demands for a resource such as a printer, processor or communications channel. Objects are added to the tail of the queue and taken off the head - compare this with the operation of a stack.
A printer buffer is a good example of a queue in action - data is written to the buffer by the computer, and read from it by the printer in the same sequence as it was written. Because printers read the data much more slowly than the computer writes it, handshaking is used to hold up the data stream when the buffer queue is full.
A typical use of queues in an operating system involves a user command which places something on a queue, e.g. a file on a printer queue or a job on a job queue, and a background process or "demon" which takes things off and processes them (e.g. prints or executes them). Another common use is to pass data between an interrupt handler and a user process.
A queue consists of an area of store indexed by two pointers, one for the head of the queue and one for the tail, together with two operations: 'push' to add a data item to the tail of the queue and 'pull' to remove the data item from the head of the queue. When an item is pushed onto the queue, the 'tail' pointer is incremented. When an item is pulled from the queue, the obvious thing to do would be to make all the items in the queue fall down the store so as to fill the vacancy left at the head of the queue. This is, however, very processor-inefficient, so the following strategy is adopted instead:
When an item is pulled from the head of the queue, the 'head' pointer is incremented. At the start, both 'head' and 'tail' pointers are zero, and the queue is empty. As items are pushed onto the queue, the 'tail' pointer increases until it reaches the last available storage location, when the queue is full. As items are pulled from the queue, the 'head' pointer increases until it catches up to the 'tail' pointer, when the queue is again empty. It is convenient to wrap both pointers around the available storage locations, so that the queue becomes circular, with the storage locations vacated by items pulled from the head of the queue being overwritten by items pushed on at the tail of the queue as the tail pointer catches up to the head pointer.
There is an UniCOMAL simulation of a working queue, called queue.zip, on the downloads page - look for it in the alphabetic index. It should make the detailed operation of a queue structure clear. It also contains a simple static stack simulation. A recursive definition of a queue structure is given in Dick Klingens' Recursion Tutorial, Chapter 5, "Data Structures".
The same features are identified as for Outcome 2, data structures and file handling. The Support Notes, P.10, state: Furthermore, it is suggested that the practical exercises for this outcome could be integrated with Outcome 4 at the implementation stage of problem-solving.
Algorithms
Two-dimensional arrays
a) DIM board$(8,8) OF 6 // Space for 64 names of up to 6 characters
b) DIM grid#(2,12) // Space for 24 integers
c) DIM spot_height(20,20) // Space for 400 real-number spot heights
0010 // Two-dimensional arrays - chess board example
0020 // MacharSoft 1998 - for Higher Still Optional Programming Unit
0030 DIM board$(8,8) OF 8
0040 set_out_pieces
0050 display_board
0060 END
0070 PROC set_out_pieces
0080 board$(,):=" " // Blank the board
0090 FOR column#:=1 TO 8 DO
0100 READ board$(1,column#) // read the outside rows
0110 board$(8,column#):=board$(1,column#)
0120 board$(2,column#):=" pawn " // set up the pawns
0130 board$(7,column#):=board$(2,column#)
0140 ENDFOR column#
0150 DATA " rook "," knight "," bishop "," king "," queen "," bishop "," knight "," rook "
0160 ENDPROC set_out_pieces
0170 //
0180 PROC display_board
0190 FOR row#:=1 TO 8 DO
0200 FOR column#:=1 TO 8 DO
0210 PRINT board$(row#,column#),
0220 ENDFOR column#
0230 PRINT
0231 PRINT
0240 ENDFOR row#
0250 ENDPROC display_board
Records
STRUC person
DIM first_name$ OF 20, last_name$ OF 20
DIM address$ OF 30, city$ OF 20
DIM age#
ENDSTRUC person
DIM member. OF person
DIM club_member(100). OF person
DIM club_member(100). - to create a list of 100 records of club members, but
DIM weight#(100) - to create a list of 100 integer weights.
PRINT club_member().first_name$ // Print out the first names of all 100 club members
PRINT club_member(). // Print out all the fields in all the records!
Program Efficiency in terms of memory and processor time
Language
Type
Operating System
Total memory used
AcornSoft COMAL
Interpreted
Acorn OS 1.2
less than 17K
UniCOMAL
Compiled
MS-DOS V6.22
just under 65K
UniCOMAL
Interpreted
MS-DOS V6.22
about 265K
Delphi
Compiled
MS-Windows 95
over 300K
The UniCOMAL Editor
LIST "filename sends the source code to a text file called "filename.LST".
LIST display_results (note: no quote marks) lists a procedure or function called display_results.
RENUM 100, 1 which renumbers starting at line 100 and going up in steps of 1. It can also be used to renumber a procedure or function:
RENUM display_results; 5000,1 which moves the procedure display_results to start at line 5000 and increment by 1s.
Using search and replace on UniCOMAL code.
Debugging facilities in program languages
This section lists the facilities usually provided with debuggers in compiled programming languages, and identifies those facilities from that list which are provided with UniCOMAL V3.11.
Debuggers
Trace tables and the TRACE command
Syntax errors
Run-time errors
Logic Errors and Trace facilities
Breakpoints
The required algorithms: frequency count, binary search, sorting and list operations
Binary Search
Frequency Counting, Sequential Files and Efficiency
intialise frequency_counter to 0
OPEN a data file for reading
WHILE there are data items left
get a data item from the file
IF data item matches target THEN
increment frequency_counter
ENDIF
END WHILE
CLOSE the data file
FUNC letter_frequency(target$, filename$)
OPEN FILE 1, filename$, READ
frequency_counter#=0
WHILE NOT EOF(1) DO
data_item$ := GET$(1,1) // Get a single ASCII character from the file
IF data_item$ = target$ THEN frequency_counter# :+ 1
ENDWHILE
CLOSE FILE 1
RETURN frequency_counter#
ENDFUNC letter_frequency
100 // Counting letter frequency 1
110 // MacharSoft, 1998: for Higher Still Programming
120 filename$ := "frequent.txt"
130 target$ := "a"
140 PRINT "There are ", letter_frequency(target$, filename$),
150 PRINT " occurrences of letter ",target$," in the file ",filename$
160 END
There are 27 occurrences of letter 'a' in the file frequent.txt
100 // Counting letter frequency 2
110 // MacharSoft, 1998: for Higher Still Programming Unit
120 filename$ := "frequent.txt"
125 FOR letter# := ORD("a") TO ORD("z") DO
130 target$ := CHR$(letter#)
140 PRINT "There are ", letter_frequency(target$, filename$),
150 PRINT " occurrences of letter ",target$," in the file ",filename$
155 ENDFOR letter#
160 END
There are 27 occurrences of letter 'a' in the file frequent.txt
There are 5 occurrences of letter 'b' in the file frequent.txt
There are 6 occurrences of letter 'c' in the file frequent.txt
:
:
There are 0 occurrences of letter 'z' in the file frequent.txt
set up an array to hold the required number of frequency counters
intialise all the frequency counters to 0
OPEN the data file for reading
WHILE there are data items left
get a data item from the file
IF data item matches any of the possible targets THEN
increment that target's frequency counter
ENDIF
END WHILE
CLOSE data file
100 // Counting letter frequency 3
110 // MacharSoft, for Higher Still Programming Unit
120 DIM letter_frequency#(97:122) // Corresponding to 'a' to 'z' in ASCII
130 // UniCOMAL automatically initialises integer arrays to 0
135 filename$ := "frequent.txt"
140 OPEN FILE 1, filename$, READ
150 WHILE NOT EOF(1) DO
160 character# := ORD(GET$(1,1)) // Get the ASCII code of a character from file 1
170 IF character# > 96 AND character# < 123 THEN
180 letter_frequency#(character#) :+ 1
190 ENDIF
200 ENDWHILE
210 CLOSE FILE 1
220 display_results
230 END
240 //
250 PROC display_results
260 FOR character# := 97 TO 122 DO
270 PRINT "There are ", letter_frequency#(character#),
280 PRINT " occurrences of letter ", CHR$(character#),
290 PRINT " in the file ", filename$
300 ENDFOR character#
310 ENDPROC display_results
Queues and buffers
Outcome 3: Implement features and use facilities of a Software Development Environment (10 hours)
"This outcome allows students to put into practice what they have learned about the features of a software development environment and about algorithms in Outcome 2. Therefore, this outcome is likely to be delivered in parallel with Outcome 2 with practical activity being used to consolidate understanding."
HSOPU - Alphabetic Index
Binary Search
Breakpoints
Debugging
Editors
Efficiency
Frequency counting
Logic Errors
Memory Efficiency
Outcome 1
Outcome 2
Outcomes
Processor efficiency
Queues
Records
Search and Replace
Run-time errors
Two-dimensional arrays
Syntax Errors
Trace Tables
First posted as "debug" 30-5-1998
Extended, renamed "hsopu" and reposted 12-6-1998
Trace tables included 13-6-1998
Efficiency included 13-6-98
Required algorithms section started 15-6-98
Note on Search and replace in editors added 17-6-98
Frequency count, sequential files and efficiency added 19-6-98
Records, STRUCs and alphabetic index added 20-6-98
Two-dimensional arrays added 26-6-98
Stacks added 23-7-98
Link to Higher Still notes added 27-7-98