
Everything a computer is good at involves doing something more than once. C has three ways to say "again", one way to stop early, and a way to choose between many cases at once. And on this machine there is one more thing to know before you write your first loop, which is that nothing you press will get you out of one that does not stop - so it has to let you out itself.
forfor (i = 1; i <= 5; i++)
printf("%d ", i);
Three parts in the brackets, separated by semicolons: what to do first (i = 1), the condition to test before each time round (i <= 5), and what to do after each time round (i++). Then the statement to repeat - one statement, or a block in braces, exactly as with if. This one prints 1 2 3 4 5.
Any of the three parts may be empty. for (;;) has no test, and goes round for ever.
while And doi = 1;
while (i <= 100) {
total += i;
i++;
}
while tests first and repeats while the condition is true - which may be no times at all. do { ... } while (condition); tests after, so the body always runs at least once:
i = 1;
do {
i = i * 2;
} while (i < 1000);
leaves i at 1024, the first power of two past 1000.
break And continueInside any loop, break leaves it at once, and continue skips the rest of this time round and goes on to the next:
for (i = 1; i <= 20; i++) {
if (i % 3 == 0)
continue;
if (i > 10)
break;
printf("%d ", i);
}
prints 1 2 4 5 7 8 10 - every third number skipped, and the loop over at the first past 10.
switchWhen one value has to be compared with several constants, switch says it once:
switch (day) {
case 1: printf("one "); break;
case 2: printf("two ");
case 3: printf("three "); break;
default: printf("other ");
}
The value is matched against each case, and execution starts at the match - and carries on into the next case unless a break stops it. case 2 above has no break, so for day 2 the program prints two three. That is not a mistake in the example; it is how switch works, and it is occasionally what you want. Mostly it is not, and mostly every case ends in break. default is where an unmatched value goes.
The four days above print one two three three other.
Now the thing to know before you run any of this. A C program on the Einstein that is busy in a loop cannot be stopped from the keyboard. CONTROL-C does nothing; BREAK does nothing. The only way out is to restart the machine, and if you have not saved your program, it is gone.
So a loop that might run for ever must look at the keyboard itself, and the Einstein library gives it a way. kbd() asks the machine whether a key is down and returns its code, or 0 if none is:
for (;;) {
n++;
if (kbd() == 'Q')
break;
}
It needs #include ?EIN.LIB?, the Einstein's own library, at the end of the file - before ?STDIO.LIB?, because the Einstein library uses the standard one, and S8's rule is that a library is read after the calls it has to satisfy. Every program that uses both ends with those two lines in that order. Every program in this course that could loop for ever has a line like this, and Q is always the key.
It is not free. kbd() asks the machine's ROM, and that takes about seven-tenths of a millisecond, so a loop with nothing else in it goes round about fourteen hundred times a second instead of ten thousand. S22 measures it properly; in a game loop that has to read the keyboard anyway it costs nothing extra. One more thing: kbd() only looks at the key. The Q that stops the program is still there afterwards, and the DOS prompt gets it. S22 has the cure.
#include STDIO.H
main()
{
int i, total;
for (i = 1; i <= 5; i++)
printf("%d ", i);
printf("\n");
total = 0;
i = 1;
while (i <= 100) {
total += i;
i++;
}
printf("1 to 100 is %d\n", total);
i = 1;
do {
i = i * 2;
} while (i < 1000);
printf("first power of 2 past 1000: %d\n", i);
for (i = 1; i <= 20; i++) {
if (i % 3 == 0)
continue;
if (i > 10)
break;
printf("%d ", i);
}
printf("\n");
}
#include ?STDIO.LIB?
Starting from
Typed as LOOPS.C; compiled and run.
What you should see
1 2 3 4 5
1 to 100 is 5050
first power of 2 past 1000: 1024
1 2 4 5 7 8 10
And the second program, FOREVER.C:
#include STDIO.H
main()
{
int n;
n = 0;
printf("Press Q to stop.\n");
for (;;) {
n++;
if (kbd() == 'Q')
break;
}
printf("stopped after %d\n", n);
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
prints its line and sits there until you press Q, when it prints how many times round it went - a few thousand, if you were quick - and 0: comes back with a Q after it, which is the key kbd() looked at and left. Press ENTER: XtalDOS looks for a program called Q, says No File, and gives you a clean prompt.
kbd() lines out of FOREVER.C and run it. Then restart the Einstein.switch, put a break after printf("two "). What do the four days print now?while (i <= 100) to while (i < 100). What is the total, and why is it that much less?12.1 Print a multiplication table for 1 to 4, in columns three wide, using two for loops one inside the other.
12.2 Print the powers of 2 from 1 upwards until the next would not fit in an int. (S9 says where that is. Think about how the loop can tell.)
12.3 Count how many numbers between 1 and 1000 are divisible by 7 but not by 5.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
| The program never comes back and no key stops it | A loop that never looks at the keyboard. Restart the Einstein; give it a kbd() test. |
A Q is sitting at the prompt after the program stops | kbd() saw the key but did not take it. ENTER, and No File, clears it; S22 shows how a program takes a key. |
A switch prints two cases for one value | The first has no break. |
A for loop runs once too many or too few | < where <= was meant, or the other way. |
not in loop or switch | A break or continue outside any loop. |
| A loop that should stop at 32767 never does | The counter rolled over to -32768 and carried on (S9). |
for (start; test; step), while (test), and do { } while (test); break leaves, continue skips; switch matches a value against cases and falls through without break. A loop cannot be stopped from outside; it watches kbd() and stops itself.
S13, Functions - your own commands, how arguments reach them, what they give back, one that calls itself, and the mistake this compiler lets through without a word.