Often we encounter situations in which we would like to repeat a command or series of commands. Each repetition is known as an iteration. Sometimes we want to iterate for a fixed number of times and sometimes we do not know when we are designing a program how many iterations are necessary. For this reason, almost all programming languages have at least one loop construct (the exception again being assembler which uses jumps). Object Pascal has 3: for, while, and repeat. A for loop uses a control variable which must be an integer and increments or decrements that variable on each loop iteration. Consider the following program which counts down from 10 and then back up to 10:
{$APPTYPE CONSOLE}
program ForLoop;
var
K : Integer;
begin
For K := 10 downto 0 do Writeln(K);
For K := 1 to 10 do Writeln(K);
Readln;
end.
If you copy/paste this program into the editor and run it you will see that it writes the numbers between 10 and 0 to the screen and then 0 to 10 on the next line. This could have also been accomplished without a loop, but it would have required a total of 21 Writeln statements.
Break and Continue are also common statements that appear in Object Pascal loops (and in most other languages for that matter). Break exits the loop immediately even if it has not completed. Continue exits the current iteration of the loop and starts the next iteration.
Excercise 2-14. Write code to solve the following problems. Remember if you need to debug any of them you have to use the {$I Debug.inc} line right after begin if you are using Lazarus.
Write a program that gives output identical to the program above but uses only a single loop instead of two. Hint: You will need to use the absolute value function Abs.
The key here is that the control variable can be used in any valid expression. Thus, we know that we want to print 21 numbers to the screen. So We can set the loop up to run from 1 to 21. The expression to print is Abs(11-K). The reason for this is that the first number written will then be Abs(11-1) = Abs(10) = 10 and the last number written will be Abs(11-21) = Abs(-10) = 10 which is what we want. Note that we could have also run the loop from 0 to 20 but the expression would then need to be Abs(10-K).
Write a program that gives output identical to the previous program but do not use the Abs function. Hint: You will need an if statement.
Here we simply write an if statement below the for loop that accomplishes the identical function of Abs. If the value expression is greater than or equal to 0 we return the expression otherwise we return the negated expression (which is exactly what the Abs function does).
Write a program that displays the powers of 2 from
to
in the following form without using the Power function in Math.
2^0 = 1
2^1 = 2
2^2 = 4
...
2^16 = 65536
Hint: You will need both the for loop control variable and an additional variable to store each sequential power of 2.
The exponent in 2^0, 2^1, 2^2, etc is simply the for loop control variable "K". The buffer variable "Buf" is initialized to 1 and then multiplied by 2 on each iteration of the loop.
Display the line 'The "X" key is down.' where X is any letter from A to Z. Hint: Start with copying and pasting the code that does this for the A key and rewrite it so that it is a loop. Keep in mind the Chr function converts a number to a character.
if Keyboard[Ord('A')].Down then
TextOut(0,0,'The "A" key is down.');
Now think of how you could write a loop for this that would loop from A to Z.
There are a couple of ways to do this. One is to loop from Ord('A') to Ord('Z'). The Break command is used so that if multiple buttons are pressed, only the first is displayed.
Another equally valid way is to use a variable of the Char type as the for loop control variable (remember, any ordinal type can be used as the for loop control variable).
Loops can be nested, but nested loops must use different control variables:
{$APPTYPE CONSOLE}
program Workspace;
var
K,J : Integer;
begin
Writeln('The multiplication tables up to 12:');
For K := 1 to 12 do
begin
For J := 1 to 12 do Write(K*J,' ');
Writeln;
end;
Readln;
end.
If you run this program you will see that it prints out the multiplication tables up to 12. Note the begin and end under the first for loop. This is necessary because this loop contains two simple statements For J := 1 to 12 do Write(K*J,' '); and Writeln;. Without the begin and end compound statement, Writeln; would not be part of the loop. Try removing the begin and end and see what happens.
Excercise 2-15. The previous code does not produce a table with aligned columns. This results because not all of the integers have the same number of digits. Using the Format function, make all of the columns have the same width of 5 characters. Hint: Refer to the SysUtils table in
Section 2.7.
Excercise 2-16. In this exercise we will write a simple program that computes the greatest common factor (GCF) and least common multiple of two numbers.
Write a boolean expression that would return True if both Num1 and Num2 were evenly divisible by SomeNum (i.e., SomeNum is a common factor to both Num1 and Num2).
We know that the mod operator will determine the remainder of an integer division. If something is evenly divisible then the remainder is 0. So Num1 mod SomeNum would be 0 if Num1 is evenly divisible by SomeNum and Num2 mod SomeNum would be 0 if Num2 is evenly divisible by SomeNum. We want an expression that returns True if both are evenly divisible. This can be accomplished with the and operator:
Write a program that reads in two integers (Num1 and Num2) and then loops through using the Boolean expression from the previous problem to write the evenly divisible factors of Num1 and Num2 that are greater than 1 to the screen. Keep in mind that there is no need to list factors greater than the smaller of Num1 or Num2 (i.e., this will determine the upper bound for the for loop). Use {$I Debug.inc} directly after begin if you need to set breakpoints for debugging.
The loop will go from 2 to Min(Num1,Num2). The Min function is in the Math unit so it will have to be included in the uses clause.
Now alter this program so that it returns only the greatest common factor. The best way to do this is to assume that there are no common factors (i.e. GCF = 1) and then update GCF when a common factor is discovered.
First we set GCF to 1 just in case no common factors are discovered (5 and 7 for example). When a common factor is discovered, we can safely set GCF to the new factor because K is always increasing (i.e. factors are discovered in ascending order).
As the program is written now, all numbers between 2 and Min(Num1,Num2) have to be tested. Rewrite the loop so that it can exit as soon as the greatest common factor is discovered.
Use downto instead of to in order to reverse the direction of the loop. That way, as soon as a common factor is determined it is guaranteed to be the greatest. The loop will go from Min(Num1,Num2) downto 2. You will also need to add a Break statement once the GCF is discovered.
Now we will write a program to determine the least common multiple. Think carefully about how to do this. If you take the smaller of the two integers and start multiplying 2, 3, 4, etc times this integer, how can you determine if a multiple of the smaller integer is also a multiple of the larger integer? Hint: If K is an integer multiplier, SmallerNum*K is an integer multiple of SmallerNum. How can we determine if SmallerNum*K is a common multiple of LargerNum?
Use mod. If SmallerNum*K is a common multiple of LargerNum then SmallerNum*K must be evenly divisible by LargerNum. Thus, SmallerNum*K mod LargerNum = 0 will be True when SmallerNum*K and LargerNum are common multiples.
Use the result of the previous problem to write the program to determine the least common multiple. Keep in mind that you need to loop only far enough to find the first common multiple (because this will be the least common multiple).