
for is for when you know how many times. Often you do not: keep asking until the answer is right; keep halving until you reach one; keep the game going until the player quits. Pascal has two loops for that, while and repeat. And a loop that goes on until something happens can go on for ever if it never does - so this section is also about getting out.
N := 100;
while N > 1 do
begin
Write(N, ' ');
N := N div 2;
end;
100 50 25 12 6 3
while checks its condition first, and if it is true, does the statement after do, then checks again, and so on. The moment the condition is false, the loop is over. If it is false to begin with, the statement is never done at all.
Something inside the loop must eventually make the condition false - here, halving N. Forget that, and the loop never ends.
repeat
Write('A number from 1 to 10: ');
Readln(N);
until (N >= 1) and (N <= 10);
repeat ... until is the other way round: it does its statements first, then checks, and goes round again until the condition is true. So it always runs at least once - which is exactly right for asking a question: you cannot check an answer before it has been given.
repeat and until enclose as many statements as you like; there is no need for begin and end.
Which to use comes down to one question: might the loop need to run no times at all? Then while. Must it run at least once? Then repeat.
while N > 0 do;
begin
N := N - 1;
end;
That semicolon straight after do is a complete, empty statement - and it is the statement the while repeats. The begin ... end below it is not in the loop at all. N never changes, and the program sits there for ever, doing nothing, as fast as it can.
A program stuck in a loop has to be stopped from outside. There are three ways, and it pays to know all of them before you need one.
CTRL-C at a question. If the program is waiting at a Readln, CONTROL and C stops it:
^C
User break, PC=0039
Program aborted
CTRL-C in a loop, with {$U+}. A program running a loop does not normally look at the keyboard, and CTRL-C does nothing. Put this as the very first line of the program:
{$U+}
and it does look, all the time, and CTRL-C stops it wherever it is. Better still, Turbo then finds the place: press ESC after the stop and the editor shows you where it was - with the semicolon above, the cursor lands right on the culprit.
{$U+} is a compiler directive: it looks like a comment, in curly brackets, but the $ makes it an instruction to Turbo about how to compile the program. It has a price. Looking at the keyboard all the time slows a loop down about twenty times over: thirty thousand trips round an empty loop take three quarters of a second without it, and about sixteen seconds with it. Use it while you are writing a program that loops, and take it out when the program works.
KeyPressed, your own way out. KeyPressed is true if a key has been pressed and not yet read. A loop can end on it:
repeat
Count := Count + 1;
until KeyPressed;
Read(Kbd, Ch);
The key is still waiting afterwards, and Read(Kbd, Ch) takes it into the Char variable Ch - so you can even see which key it was. Asking KeyPressed costs about as much time as {$U+} does, so it is for loops that do something worth doing each time round, not for tight counting.
And if all else fails, restart the Einstein, which loses anything not saved - which is why S4 said to save before you run. Under the emulator BREAK does nothing.
program Guesses;
var
G, Tries: Integer;
begin
Tries := 0;
repeat
Write('Guess (1-10): ');
Readln(G);
Tries := Tries + 1;
if G < 7 then Writeln('Higher.');
if G > 7 then Writeln('Lower.');
until G = 7;
Writeln('Right, in ', Tries,
' tries.');
end.
Starting from
Turbo freshly started, Y, a new work file called GUESSES.
What you should see
With 3, 9 and 7 as the guesses:
Guess (1-10): 3
Higher.
Guess (1-10): 9
Lower.
Guess (1-10): 7
Right, in 3 tries.
Tries := Tries + 1;. How many tries does it say now?until G = 7 to until G = 70. Guess 7. What happens - and how do you get out?while instead of repeat. What do you have to do to G before the loop, and why?14.1 Ask for a number, and keep halving it (with div) until it reaches 1, printing each result. Start with 100.
14.2 Keep asking for a number from 1 to 10 until you get one, then thank the person and print it.
14.3 Count as fast as you can until a key is pressed, then print how far you got.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
| The program starts and nothing happens, for ever | A loop whose condition never changes - often a semicolon after do. |
| CTRL-C does nothing | The program is in a loop and was not compiled with {$U+} as its first line. Restart the Einstein; add {$U+} while you find the fault. |
| A program has become very slow | {$U+}, or KeyPressed, inside a busy loop. Take {$U+} out once the program works. |
A while loop never runs | Its condition is false to begin with. |
A repeat loop runs once when it should not have | repeat always runs once. Use while. |
while checks first and may run no times; repeat ... until checks last and always runs once. A semicolon after do makes an empty, endless loop. CTRL-C stops a program at a Readln, and in a loop only if the program starts with {$U+} - which slows loops greatly, so take it out when done. KeyPressed lets a loop end when a key is pressed, and Read(Kbd, Ch) then reads that key.
S15, Your Own Commands - procedures: giving a name to a piece of program and using it as often as you like.