Algorithms
and Lazarus
Structural
Elements: ITERATION
Repetition
is one thing computers are very good at. One of many reasons that they
now control many aspects of manufacture is their ability to repeat actions
(without error hopefully) over long periods of time. Iteration in a programming
system can be subtle or explicit in effect your whole system is
continually waiting until you do something it is stuck in an execution
cycle.
|
POST-TESTED INDEFINITE
do
the task and then ask if you should do it again
Use this sort of loop
when you need to do the task AT LEAST once, but possibly lots of
times
repeat ... until
|
|
PRE-TESTED INDEFINITE
ask
if you have finished doing the task yet - if not, do the dask
Use this loop when unsure
if you need to perform the task at all
while ..do
|
|
PRE-TESTED DEFINITE
perform
the task a fixed number of times
Use this type of loop
when you can determine, beforehand, how many times the task needs
to be performed
for... to .. do
|
|
TIMER-BASED
each
tick, do the task
|
There are a number of different
classifications of iterative processes (or loops)
definite
where the exact number of
'cycles' are known before-hand
event-driven
where some regular (or
programmed) event triggers the task to be done again (like a timer
tick). It is worth noting that most forms of iteration must be very
carefully used in an event-driven program as, generally, they are
EXCLUSIVE processes (ie. nothing else can be happening while the loop
is being executed) - this is different to timer-based iteration.
2 different standard
iterative strategies are common:
pre-tested loop
|
post-tested loop
|
Syntax: repeat
[statement] {;
[statement] }
until p
where p is a BOOLEAN expression (something that can be true or false).
Inside the loop, there
must be the ability for p to become TRUE; otherwise ENDLESS LOOP.
eg. x := 2;
repeat
showmessage ('One more time');
until x > 10; {is an endless loop}
eg2. repeat
showmessage ('Over and Over');
until FALSE; {also endless}
Endless loops are only deployed
for good reasons.
It is possible for multiple
statements between the repeat and until. The repeat ... until behaves
in much the same way as a begin ... end in encapsulating a parcel of
tasks.
It is possible to use
a variable to control the loop. Such a variable is often termed a loop
variable. By changing the value of the loop variable, it is possible
to create the conditons necessary for the loop to terminate
eg3.
procedure TForm1.Button1Click(Sender: TObject);
var answer : string;
x : integer;
begin
x := 1;
repeat
answer := inttostr(x)+'^2 = '+inttostr(x*x)
showmessage(answer);
inc(x)
until x > 10
end;
Repeat..until is used
when UNCERTAIN of the number of repetitions SO LONG AS AT LEAST ONE
is required.
Case Study: Write a
buttonclick handler that repeatedly asks for test scores (out of 30),
terminating with a ZERO (0), and then printing out class average.
procedure TForm1.Button1Click(Sender: TObject);
{prompts for test scores out of 30, terminating with }
{a zero, and then reports average}
var total, average : real;
numinclass : integer;
mark, result : string;
begin
{initialisation}
total := 0;
numinclass := 0;
{input loop}
repeat
mark := inputbox('Data Entry','Please enter a score','0');
if mark <> '0'
then begin
inc(numinclass); {tally of num of marks}
total := total + strtoint(mark) {tally of marks}
end
until mark = '0'; {the sentinel value}
{output}
average := total/(numinclass);
result := 'Class average = ' + floattostr(average);
showmessage(result)
end;
Notice the above program is buggy
as it will accept zero scores and blithely attempt to calculate the average
of zero scores (dividing by zero and freaking out the machine in the process)
- can you devise a test to prevent this? This event handler does not check
the score is out of 30 - can you make it do so?
|
CLASS AVERAGE
Repeatedly ask for marks out of 100 for a test, tallying as you
go until a sentinel value is reached, then output the average
for that group. Error trap as much as possible.
|
|
See
a SDC Solution
|
|
McMENU
Repeatedly ask users for choices off a menu of 4 items, each time
the user makes a selection, update the tally for that product. When
the user indicates they are finished the order (via a sentinel
value, present an itemised bill
|
|
See
a SDC Solution - Goto an exercise
on this
|
|
BUZZY BEE
Place a TShape (our Honeypot) somewhere on the screen, then randomly
place a Button (our bee) on the screen, then continually update
the position of the Button (randomly) until it lands on the TShape
- report the number of re-positions necessary to achieve this
|
|
See
a SDC Solution
|
Syntax: while p do
[ statement ]
where p is BOOLEAN, and statement may be compound (ie. begin
.... end)
A while..do loop is used if
the statements inside the loop may not need executing at all (ie 0..many
iterations). The while determines if the statement needs to be
executed - if the while returns a true, then the statement is executed,
otherwise the next part of your program is executed.
They are used when it is difficult
to predict how many iterations are necessary. They are NOT the same as
repeat..until statements which execute the enclosed task at least once.
eg1. procedure TForm1.Button1Click(Sender: TObject);
var
answer : string;
a : integer;
begin
a := 1;
while a <= 10 do
begin
answer := inttostr(a)+'^2 = '+ inttostr(a*a);
showmessage(answer);
inc(a);
end
end;
Syntax:
for identifier := val1 [down]to val2 do
[ statement ]
eg1:
procedure TForm1.Button1Click(Sender: TObject);
var counter : byte;
answer : string;
begin
for counter := 1 to 10 do
begin
answer := inttostr(counter)+ ': over and over';
showmessage(answer)
end;
end;
We use for..do loops in situations
when we know how many times we want a task executed. These loops are very
commonly used for many different things (especially when dealing with
compound data types like arrays).
A for..do loop uses an ordinal
loop variable to control the loop, and can either ascend or descend in
value according to the loop declaration
eg2: procedure TForm1.Button1Click(Sender: TObject);
var nam : char;
begin
for nam := 'A' to 'E' do
showmessage(nam)
end;
The identifier used as
the counter of the loop can also be used inside the loop.
eg3: procedure TForm1.Button1Click(Sender: TObject);
var answer : string;
num : integer;
begin
for num := 1 to 5 do
begin
answer := inttostr(num)+'*7 = '+inttostr(num*7);
showmessage(answer);
end;
end;
The loop cycles exactly
as many times as there are values for the identifier
The statement may be
compound (eg begin .. end)
If val1 > val2 then
loop will not be entered at all in standard form.
eg4: for thing := 20 to 10 do ... DO ISN'T ENTERED
but for thing := 20 downto 10 do ... IS ENTERED
NEVER artificially alter
the loop variables value inside the loop.
eg5: for i := 1 to 10 do
begin
showmessage ('hello');
inc(i) <-------ERROR
end
If there is a need to manually
change the value of the loop variable, then the FOR..DO loop is not
the one to use. (most likely you want to use a while do instead)
To step up by increments
other than 1, probably best to use another loop structure. An 'acceptable
solution' may be:
eg6: procedure TForm1.Button1Click(Sender: TObject);
var val, step, counter : integer;
answer : string;
begin
val := 1; step := 3;
for counter := 1 to 5 do
begin
answer := inttostr(val);
showmessage(answer);
val := val + step <-----not changing the
end; loop variable
end;
Premature exit from the
loop is ABSOLUTELY FORBIDDEN
DON'T assume that the
loop variable finishes up (after the loop terminates normally) at the
last value assigned --> this is not standard.
|