Control Structures

advertisement
CHAPTER
10
CONTROL STRUCTURES
In this chapter you will learn about
 The selection structures such as the ‘if’ construct, the ‘if-else’ construct, the conditional
operator and the ‘switch’ statement.
 The repetition structures such as the ‘while’ loop, ‘do-while’ loop, and the ‘for’ loop.
 The use of ‘continue’ and ‘break’.
144
Chapter 10  Control Structures
10.1 Introduction
In a procedural language, the flow of execution is determined by the
control structures of the program. All programs can be written using
these three control structures:
 Sequence
 Selection
 Repetition
These control structures came about with the introduction of
structured programming many years ago, to counteract the widespread bad
habit of programmers at that time – the indiscriminate use of ‘goto’
statements. It was apparent that programs with ‘goto’ statements are hard
to understand and modify, costing companies a great deal of money and
manpower. Structured programming embraces good programming
techniques and practice, among which is the eradication of ‘goto’ in
programs.
A control structure is a combination of individual instructions into a
single logical unit with one entry point and one exit point.
Sequential flow is specified by a compound statement, consisting of a
group of statements in a block, delimited by braces:
{
statement1;
statement2;
.
.
statementn;
}
A selection structure allows for choice among alternative statements,
and a repetition structure allows an action to be repeated while some
condition remains true, as depicted in the flowcharts below. We will
study these structures in details.
No
condition
action-1
Yes
action-2
action
Yes
condition
No
Selection structure
Repetition structure
10.2  Selection Structure
145
10.2 Selection Structure
C provides a few versions of the selection structure: one-way branch, twoway branch, and multi-way branch.
10.2.1 The ‘if’ Construct
The ‘if’ construct allows some action to be taken when a condition is met.
The action could be a single statement, or a compound statement that
comprises a number of statements. The syntax for an ‘if’ construct with a
single-statement action is
if (expression)
statement;
If the expression is nonzero (true), then statement is executed; otherwise,
statement is skipped and control passes to the next statement in the
program. Note the use of indentation which is a recommended practice
to mark out the statement that is associated with the ‘if’ construct.
For example,
fine = 20;
if (speed > 50)
fine += 10;
printf("Fine is %d\n", fine);
Here, ‘fine’ will remain at 20 if the condition (speed > 50) is false.
Otherwise, ‘fine’ will be increased to 30.
Compound-statement Action
Sometime, the course of action we want to take when the ‘if’ condition is
true consists of a compound statement (a sequence of statements). In this
case, we use the braces to mark off the compound statement. The syntax
is hence:
if (expression)
{
compound-statement;
}
Braces may also be used for single-statement action, sometimes for
the sake of readability, but that is not required syntactically.
With compound-statement, instead of writing
if (a > b)
max = a;
if (a > b)
printf("%d is larger than %d\n", a, b);
146
Chapter 10  Control Structures
we may now write this more efficient version:
if (a > b)
{
max = a;
printf("%d is larger than %d\n", a, b);
}
Flags
Making use of the fact that zero is false and non-zero value is true, we
could save a few keystrokes in some cases. For example, suppose
‘attended’ is an integer variable to indicate if a student has attended a
course. It contains zero if he has not attended, or 1 if he has. Such a
variable that stores zero or 1, simulates a Boolean variable1, and is known
as a flag. Suppose ‘attendance’ is an integer variable that counts the
number of students in a course. A code fragment could look like this
(this code is most likely within a loop in order to perform the counting):
if (attended == 1)
attendance++;
The above could be replaced by:
if (attended)
attendance++;
which achieves the same result. Why?
Similarly, if we want to count the number of absentees, we could
have:
if (attended == 0)
{
absentees++;
printf("One more absentee.\n");
}
or this shorter version favoured by experienced programmers:
if !(attended)
{
absentees++;
printf("One more absentee.\n");
}
1
A Boolean variable contains a Boolean value, which is either ‘true’ or ‘false’.
10.2.1  The ‘if’ Construct
147
Naming a Flag
Note that a flag should be named appropriately, otherwise it might cause a
lot of confusion. Do not simply name a flag ‘flag’; this does not give any
information to the readers. In the above example, the flag ‘attended’ is
named as such, and readers would intuitively assume that if it contains the
value 1 (true), it represents what the name suggests – he attended the
course. If it contains zero (false), it represents the opposite of what the
name suggests – he did not attend the course. If the flag is named ‘absent’
instead, but means present if it contains 1, and absent if it contains zero,
this will go against expectation and create confusion!
Nested ‘if’ statements
Since an ‘if’ construct is a statement, it can appear in the body of another
‘if’ construct. This gives rise to nested ‘if’ statements, as shown below:
if (exam >= 80)
if (project >= 90)
grade = 'A';
The above code could also be written using a single ‘if’ construct with
compound condition:
if (exam >= 80 && project >= 90)
grade = 'A';
Lazy (short-circuit) evaluation
We have mentioned in Chapter 8 that a lazy or short-circuit evaluation is
applied to a compound condition – the evaluation stops as soon as the
value of the logical expression can be determined. The evaluation is carried
out from left to right.
In the example above, if the expression (exam >= 80) is false, the
second expression (project >= 90) would not need to be evaluated, since
the whole compound condition is false.
Similarly, for a compound logical expression like this:
if (bank_bal < 0.0 || expenses > 100.0)
printf("Red alert!\n");
If bank_bal is less than 0.0, the whole condition is true, and so the
second logical expression need not be evaluated.
148
Chapter 10  Control Structures
Complementing a Condition
Negating or complementing a logical expression means changing the
polarity of the expression. For example, !(a == 30) is equivalent to (a !=
30), and !(a > b) can be rewritten as (a <= b). How about negating a
compound logical expression?
We may use the DeMorgan’s Theorem for this purpose. The theorem
states that:
 NOT(a AND b) is equivalent to NOT(a) OR NOT(b)
 NOT(a OR b) is equivalent to NOT(a) AND NOT(b)
Hence, in C we have:
 !(expr1 && expr2) is equivalent to !(expr1) || !(expr2)
 !(expr1 || expr2) is equivalent to !(expr1) && !(expr2)
For example, the following two logical expressions are equivalent.
!(age > 25 && (status == 'S' || status == 'D'))
(age <= 25) || (status != 'S' && status != 'D'))
Common Mistakes
As discussed in Chapter 8, floating-point numbers are inexact. Hence,
you should not use the equality (==) or the inequality (!=) test on
floating-point numbers. In testing for equality, compute the difference
of the two values instead and check that the difference is small enough.
In testing for inequality, you may compute the difference and check that
it exceeds a threshold, or you may simply use other relational operators
like <, <=, >, >= depending on the situation.
The equality (==) operator is often mixed up with the assignment (=)
operator, and that could result in hard-to-spot errors. Some beginners
also tend to omit the parentheses around the condition.
It is a mistake to put a semicolon after the condition, like this:
if (a > b);
printf("a is larger than b\n");
This would create an empty statement for the ‘if’ construct. The
printf() statement is now outside the ‘if’ construct, and thus it will be
executed regardless of the truth value of the ‘if’ condition.
10.2.1  The ‘if’ Construct
149
Sometimes, mistakes might be made inadvertently in converting
conditions from English to C. For example, suppose we want to check if a
variable x lies within a range [lower, upper]. In mathematics, we are used
to writing lower ≤ x ≤ upper, so some may translate it directly into the
following code:
if (lower <= x <= upper)
...
The condition is wrong. Test it out with some values, say, lower=10,
upper=30, and various values for x, such as 15, 20, 40, etc. The right way
to write the condition is:
if (lower <= x && x <= upper)
Since <= has higher precedence than &&, the above is equivalent to:
if ((lower <= x) && (x <= upper))
Another example: x and y are greater than z. A careless translation to
C would result in:
if (x && y > z)
which is again wrong (why?). The right way is:
if (x > z && y > z)
Another common mistake is the omission of the braces in an ‘if’
construct with compound-statement action. For example, in the code
below, the braces are forgotten:
if (a > b)
max = a;
printf("%d is larger than %d\n", a, b);
Since indentation is meant for human consumption, and is ignored by
the compiler, it does not automatically turn the two indented lines into a
compound statement. The compiler would simply treat the body of this ‘if’
construct as a single-statement action, due to the absence of the braces.
Hence, the printf() statement is considered outside the ‘if’ construct, and
consequently, regardless of the truth value of the condition, the printf() line
is always executed.
You are to guard against all these easy traps.
150
Chapter 10  Control Structures
10.2.2 The ‘if-else’ Construct
The ‘if-else’ construct provides a two-way branch in which one of the
two alternative paths is taken depending on the truth value of the
condition. The format of the ‘if-else’ construct is:
if (expression)
statement1 ;
else
statement2 ;
or, with compound-statement actions, we have:
if (expression)
{
compound-statement1 ;
}
else
{
compound-statement2 ;
}
For example,
if (count == 0)
ave = 0.0;
else
ave = (float) total/count;
if (score1 < score2)
{
better_score = score2;
printf("score2 is better\n");
}
else
{
better_score = score1;
printf("score1 is better\n");
}
The use of ‘if-else’ avoids redundant code such as this:
if (count == 0)
ave = 0.0;
if (count != 0)
ave = (float) total/count;
In the above code, two conditions will have to be tested. Using the
‘if-else’ construct, only one condition is necessary.
10.2.2  The ‘if-else’ Construct
151
Style
There are a few commonly accepted styles on the placement of the braces
in the ‘if’ and ‘if-else’ statements. One version has been shown earlier on.
Another version, favoured by some (including myself), has this format:
if (expression) {
compound-statement1 ;
}
else {
compound-statement2 ;
}
Omit the ‘else’ block if there is no ‘else’ part. This version takes up
fewer lines. I will stick to this form for the rest of the book.
Removing Common Statements
You should ensure that there are no duplicated statements in the ‘if’ and
‘else’ parts of the construct, since that would be redundant.
if (a < 0) {
count++;
neg++;
printf("Enter an integer: ");
scanf("%d", &k);
}
else {
count++;
pos++;
printf("Enter an integer: ");
scanf("%d", &k);
}
The common sections should be moved out of the ‘if’ construct, as
shown below:
count++;
if (a < 0)
neg++;
else
pos++;
printf("Enter an integer: ");
scanf("%d", &k);
152
Chapter 10  Control Constructs
Logical Assignment for Flags
Consider this example where a flag ‘snr_citizen’ is assigned 1 to represent
a senior citizen, or zero to represent non-senior citizen:
if (age >= 65)
snr_citizen = 1;
else
snr_citizen = 0;
In cases like this, we may write a single assignment statement without
using the ‘if’ statement:
snr_citizen = (age >= 65);
As another example, the code below sets the variable ‘even’ to 1 if n
is even, or zero if n is odd.
if (n % 2 == 0)
even = 1;
else
even = 0;
The short form would be:
even = (n % 2 == 0);
The statement is more succinct, and achieves the same purpose. You
are encouraged to use such form whenever appropriate.
There is even a more cryptic way of writing the code:
even = !(n % 2);
This is a favoured way of coding by C experts, but novice
programmers should double-check the code if they want to follow suit.
Nested ‘if-else’ statements
Just as we have nested ‘if’ statements, we can also have nested ‘if-else’
statements. For example:
if (marks < 50)
grade = 'F';
else
if (marks < 70)
grade = 'B';
else
grade = 'A’;
The fail grade is given if the marks fall below 50, and execution
continues on to the next statement after the ‘if’ construct (the whole
code above is considered as one single compound statement).
Otherwise, the marks is compared to 70, and ‘B’ grade is awarded if it is
below 70, or ‘A’ grade if it is above or equal to 70. A fuller version with
more grades will be shown later.
10.2.2  The ‘if-else’ Construct
153
Having nested ‘if-else’ statements gives rise to the possible question of
determining which ‘if’ the ‘else’ part is associated with. In the above code,
the first ‘else’ is associated with the first ‘if’, and the second ‘else’ with the
second ‘if’. What about this code below?
if (a == 1)
if (b == 2)
printf("***\n");
else
printf("###\n");
The code is not indented on purpose. Which ‘if’ is the ‘else’ associated
with? If the ‘else’ is associated with the first ‘if’, then ### will be printed
if a is not equal to 1. If the ‘else’ is associated with the second ‘if’, then
### will be printed if a is 1, and b is not 2.
In this case, the ‘else’ is matched to the second ‘if’. In general, an ‘else’
is associated with the nearest ‘if’ statement. Now, we will add indentation
to the code above to reflect the actual way it is interpreted by the compiler:
if (a == 1)
if (b == 2)
printf("***\n");
else
printf("###\n");
Suppose you want to override this interpretation; you want to attach
the ‘else’ to the first ‘if’ instead. In this case, you would need to mark out
the inner ‘if’ in a block, like this:
if (a == 1) {
if (b == 2)
printf("***\n");
}
else
printf("###\n");
Now, the ‘else’ will not be attached to the inner ‘if’, because it is outside
the block where the inner ‘if’ lies, and hence, it will be matched to the outer
‘if’ instead.
Let’s look at another example. The code below is wrong:
if (a == 0)
if (b == 0)
printf("Both a and b are zeros.\n");
else
c = b/a;
The ‘else’ is attached to the second (nearer) ‘if’, and so when a is zero
and b non-zero, the statement c = b/a will be carried out, resulting in a
division-by-zero error.
154
Chapter 10  Control Structures
The correct code should be:
if (a == 0) {
if (b == 0)
printf("Both a and b are zeros.\n");
}
else
c = b/a;
This code will not result in a division-by-zero error since the
statement c = b/a will only be executed when a is non-zero.
Coming back to the ‘if’ statement on grade assignment, this is the full
version:
if (marks < 50)
grade = 'F';
else
if (marks < 60)
grade = 'D';
else
if (marks < 70)
grade = 'C’;
else
if (marks < 80)
grade = 'B';
else
grade = 'A';
Note that following the style for indentation results in a code that is
‘skewed’ to the right and takes up many lines for complex ‘if’ statements.
As such a structure is commonly encountered in practice, an alternative
format which is widely accepted, is used:
if (marks < 50)
grade = 'F';
else if (marks < 60)
grade = 'D';
else if (marks < 70)
grade = 'C’;
else if (marks < 80)
grade = 'B';
else
grade = 'A';
This format gives a flatter layout without affecting readability.
10.2.2  The ‘if-else’ Construct
155
Common Mistakes
As explained earlier, one mistake is to let an ‘else’ matched to the wrong
‘if’. The remedy is to use braces to block a section of the code if necessary.
Sometimes, a semicolon is added erroneously after the ‘if’ block:
if (a == b) {
a++;
b--;
};
else
a = b;
The semicolon after the closing brace (}) creates an empty statement,
and consequently the ‘else’ has no ‘if’ to attach to.
10.2.3 Conditional Operator (?:)
C provides the conditional operator which is the only ternary operator that
takes three operands. The operator with the operands form a conditional
expression with this syntax:
condition ? expr1 : expr2
The first operand is the condition, the second operand is the value if the
condition is true, and the third operand is the value if the condition is false.
For example,
max = (a > b ? a : b);
This cryptic statement has a conditional expression on the right of the
assignment. The conditional expression
(a > b ? a : b)
is evaluated to the value of a if a is larger than b, or to the value of b
otherwise, and the value is then assigned to max. Hence, if a is larger than
b, the value of a is assigned to max. If b is larger than or equal to a, then
the value of b is assigned to max. This is equivalent to:
if (a > b)
max = a;
else
max = b;
Similarly, the two pieces of code below are equivalent:
if (marks < 50)
printf("Failed\n");
else
printf("Passed\n");
printf("%s\n", grade < 50 ? "Failed" : "Passed");
Chapter 10  Control Structures
156
10.2.4 The ‘switch’ Construct
The ‘switch’ is a multi-way selection statement generalising the ‘if-else’
statement. The syntax is as follows:
switch (expression) {
case v1: s1 ;
break;
case v2: s2 ;
break;
...
default: sn ;
break; /* optional break */
}
This construct may only be used to test a constant integral
expression, that is, the value of the expression should be of type int or
char. The vi’s are integral values (integers or characters), and the si’s are
compound statements.
After the expression is evaluated, control jumps to the appropriate
‘case’ label, and the statements in si are executed. Usually, the last
statement before the next case is a ‘break’ statement. If there is no
‘break’ statement, the execution will fall through to the next statement in
the succeeding case. There may be at most one default label in a ‘switch’
construct. The purpose of the default case is to capture cases that are
not enumerated.
Here is an example:
switch (class) {
case 'B':
case 'b': printf
break;
case 'C':
case 'c': printf
break;
case 'D':
case 'd': printf
break;
case 'F':
case 'f': printf
break;
default : printf
}
("Battleship\n");
("Cruiser\n");
("Destroyer\n");
("Frigate\n");
("Unknown ship class %c\n",
class);
10.3  Repetition Structure
157
10.3 Repetition Structure
In our daily life, many activities are repetitive in nature. For example, fill
the bottle until it is full, run ten laps around the track, wait until you are
called, and so on. In data processing, we have operations such as read
students’ records one at a time, until the end of the file; add a list of fifty
numbers; or repeatedly request for a data until it is valid.
In programming, such repeated actions are known as loops. A loop is
a group of instructions that is repeatedly executed while some condition
stays true. A infinite loop is one that goes on forever, and that must be
avoided.
There are basically two types of loop control: one is known as countercontrolled repetition where the number of times of repetition is known
beforehand, and the other is the sentinel-controlled repetition where the loop
stops when a special sentinel value is encountered, or when the
terminating condition is met.
C provides 3 loop constructs: ‘while’, ‘for-while’ and ‘for’.
10.3.1 The ‘while’ Construct
The ‘while’ statement is a pre-test condition-controlled loop construct. It
has the form:
while (expression)
statement ;
The expression is the loop condition and it is evaluated. If it is non-zero
(true), the statement in the loop body is executed and control is then passed
back to the beginning of the loop, and the condition tested again. If it is
zero (false), then the loop terminates and control is passed to the next
statement after the ‘while’ construct. It is possible that the loop body is
not executed at all, if the loop condition is false at entry.
As usual, the loop body could be a compound statement, in which case
it must be enclosed in braces.
The code below prints n asterisks across the screen.
count_star = 0;
while (count_star < n) {
printf("*");
count_star++;
}
Assuming that n is an integer variable that contains the value 5 (or it
could be a constant macro that represents 5), the above code prints 5 *’s.
We say that the loop goes through 5 iterations. Trace the code.
158
Chapter 10  Control Structures
The code could be rewritten as follows:
count_star = 0;
while (count_star++ < n)
printf("*");
Summing is a very common task in programming. The code below
computes the sum of the first 100 positive integers.
int num = 1;
int total = 0;
/* declaration and */
/* initialisation */
while (num <= 100) {
total += num;
num++;
}
If the num++ statement is removed, and the condition (num <=100)
is changed to (num++ <=100), following the previous example, would
the amended code compute the same result?
Which of the following is/are equivalent to the example above?
int num = 1;
int total = 0;
while (num <= 100) {
total += num;
++num;
}
int num = 1;
int total = 0;
while (num <= 100)
total += num++;
int num = 1;
int total = 0;
while (num <= 100)
total += ++num;
The variable num above serves as the loop control variable in the loop
statement. The loop control variable determines whether the loop
should continue or terminate. The following operations involving the
loop control variable are required for a successful loop construct:
 Initialisation – before the loop is entered, the loop control
variable must be initialised.
 Testing – condition involving the loop control variable is tested
before the start of each loop iteration; if condition is true, loop
body is executed.
 Updating – loop control variable is updated during each
iteration (usually at the beginning or the end of the loop body).
10.3.1  The ‘while’ Construct
159
Counter-control repetition and Sentinel-control repetition
When the number of iterations is known, a counter-control method is
more appropriate. In this method, a counter is used to keep track of the
number of iterations.
Sentinel-control is a more general approach. It is handy when the
number of iterations cannot be determined beforehand, such as reading a
list of values without knowing how many values are there. A special value,
one that does not fall within the range of the data values, might be chosen
to indicate the end of the list.
The code below illustrates counter-control repetition in summing a list
of 10 values entered by the user:
#define N 10
. . .
total = 0;
count = 1;
while (count++ <= N) {
printf("Enter score: ");
scanf("%d", &score);
total += score;
}
avg = (float) total / N;
printf("Average is %.2f\n", avg);
The code below illustrates sentinel-control repetition. The sentinel
value of –1 is chosen to indicate the end of the list of scores.
#define SENTINEL –1
. . .
total = 0;
count = 0;
printf("Enter score, –1 to end: ");
scanf("%d", &score);
while (score != SENTINEL) {
total += score;
count++;
printf("Enter score, –1 to end: ");
scanf("%d", &score);
}
if (count) {
avg = (float) total/count;
printf("Average is %.2f\n", avg);
}
else
printf("No scores were entered\n");
160
Chapter 10  Control Structures
The disadvantage of user-defined sentinel such as –1 above is that the
chosen sentinel value must not be a valid data. Hence, the range of valid
values must be known first. If this is not possible, then setting an
arbitrary sentinel is taking a risk. The more general solution is to use the
system-defined end-of-file (EOF) character, but this topic will be
deferred until CS1101C.
10.3.2 The ‘do-while’ Construct
The Pascal programming language provides a ‘repeat-until’ construct
beside the ‘while-do’ construct. In C, there is no ‘repeat-until’, but there
is a ‘do-while’ construct.
The ‘do-while’ statement is a loop structure with a post-test condition,
in contrast to the pre-test condition in the ‘while’ statement. A post-test
condition loop structure means that the condition is tested after the loop
body. This implies that the loop body is executed at least once.
The syntax for the ‘do-while’ construct is as follows:
do
statement ;
while (expression);
Below are two examples that illustrate the use of ‘do-while’
constructs.
count = 1;
do {
printf ("%d ", count);
} while (++count <= 10);
do {
printf("Enter a letter A thru E: ");
scanf("%c", &letter);
} while (letter < 'A' || letter > 'E');
The second example above shows the common technique to request
for data repeatedly until it is valid.
10.3.3 Flag-controlled Loops
When the loop condition becomes too complex, flags may be used to
simplify the code, and makes it easier to read and understand. However,
the name of the flag must be apt for the benefit of readability to be seen.
Here is an example of a flag-controlled loop:
valid = 1;
while (valid) {
printf("Enter a letter A thru E: ");
scanf("%c", &letter);
valid = (letter >= 'A' && letter <= 'E');
}
10.3.4  The ‘for’ Construct
161
10.3.4 The ‘for’ Construct
The ‘for’ statement is another pre-test condition-control loop structure. It
provides a more compact form for counter-controlled loops.
The syntax of the ‘for’ construct is as follows:
for (initialisation-expression ;
loop-condition ;
update-expression)
statement ;
The ‘for’ construct is equivalent to this ‘while’ construct:
initialisation-expression ;
while (loop-condition) {
statement ;
update-expression ;
}
An example:
for (count_star = 0;
count_star < N;
count_star++)
printf ("*");
/* init
*/
/* condition */
/* update
*/
The initialisation-expression and update-expression are often commaseparated lists of expressions. The comma operator evaluates the list from
left to right. For example,
for (x = 1, total = 0; x <= 100; x++)
total += x;
In this case, the initialisation-expression consists of two expression,
namely, x = 1 and total = 0.
Any of the three expressions in the ‘for’ header can be omitted, but the
semi-colons must remain. If the initialisation-expression is missing, then the
loop does not perform any initialisation steps before executing the loop
body. You have to ensure that all essential initialisation steps are done
before the loop, as shown here:
x = 1;
total = 0;
for (; x <= 100; x++)
total += x;
If the update-expression is missing, the loop does not perform any update
operation. Again, you must ensure that the necessary update operations
are done in the loop body.
for (x = 1, total = 0; x <= 100;) {
total += x;
x++;
}
162
Chapter 10  Control Structures
If the loop-condition is missing, then the test is always true. This means
that the following loop is infinite:
for (x = 1, total = 0; ; x++)
total += x;
10.3.5 Common Mistakes
Here are a few common mistakes when it comes to programming loops.
Adding a semi-colon at the wrong place. For instance, in this code:
for (x = 1; x <= 10; x++);
printf("%d\n", x);
as well as in this code:
x = 1;
while (x <= 10);
printf("%d\n", x++);
the semi-colons at the end of the ‘for’ line and the ‘while’ line create
empty statements, and so the printf() statements no longer fall inside the
loop body. What output do the above two codes produce?
Omitting semi-colons in the ‘for’ header, and mixing up semi-colons
with commas, are also quite common.
Another common mistake is the ‘off-by-one’ error, where the loop
executes one more time or one fewer time than desired. For example,
the following code executes n+1 times:
for (count = 0; count <= n; ++count)
sum += count;
10.4 The ‘break’ and ‘continue’ Statements
The ‘break’ and ‘continue’ statements are used to alter the flow of
control. (The ‘break’ statement has also been covered in the ‘switch’
construct.) Sometimes, we may want to terminate a loop, or skip a
section of the loop body in an iteration, under some special condition.
Without the provision of ‘break’ and ‘continue’, the code could still be
written, but usually it would appear rather clumsy. However, the use of
‘break’ and ‘continue’ must be moderated. They should only be used to
prevent awkward codes, not for convenience.
The ‘break’ statement in a ‘switch’, ‘while’, ‘do-while’ or ‘for’
structure causes immediate exit from the structure. The example below
demonstrates the effect of a ‘break’ statement in a loop body.
10.4  The ‘break’ and ‘continue’ Statements
163
#include <stdio.h>
main()
{
int x;
for (x = 1; x <= 10; x++) {
if (x == 5)
break;
/* break loop only if x == 5 */
printf("%d ", x);
}
printf("\nBroke out of loop at x == %d\n", x);
return 0;
}
The code produces the output below:
1 2 3 4
Broke out of loop at x == 5
The ‘continue’ statement in a ‘while’, ‘do-while’ or ‘for’ structure skips
the remaining statements in the body, to the next iteration of the loop, as
shown below:
#include <stdio.h>
main()
{
int x;
for (x = 1; x <= 10; x++) {
if (x == 5)
continue;
/* skip remaining code in
loop only if x == 5 */
printf("%d ", x);
}
printf("\nUsed 'continue' to ");
printf("skip printing the value 5\n");
return 0;
}
The output for this code is:
1 2 3 4 6 7 8 9 10
Used 'continue' to skip printing the value 5
164
Chapter 10  Control Structures
10.5 Nested Loops And Combined Structures
Just as we have nested ‘if’ and ‘if-else’ statements, we could also build
nested loops, or combine selection structures with repetition structures.
In fact, it is the combination of these various structures that offers a rich
set of possibilities. A good algorithm is usually a clever application of the
right combination.
The following code use a nested ‘for’ loop to print a pattern of
asterisks:
for (i = 1; i <= 4; ++i) {
for (j = 1; j <= 6; ++j)
printf("*");
printf("\n");
}
The output is 4 rows by 6 columns of *’s:
******
******
******
******
What about this code?
for (i = 1; i <= 4; ++i) {
for (j = 1; j <= i; ++j)
printf("*");
printf("\n");
}
The output this time is:
*
**
***
****
Another example:
for (i = 1; i <= 6; ++i) {
if (i <= 3)
printf("%d", i);
else
for (j = 1; j <= i; ++j)
printf("*");
printf("\n");
}
Can you work out the output before turning to the next page for the
answer?
10.5  Nested Loops And Combined Structures
165
The output is:
1
2
3
****
*****
******
Knowing how to combine control structures is an essential skill in
programming and solving algorithmic problems. You need to have plenty
of practice on this.
10.6 Summary
This chapter covers the important topic on control structures. Control
structures are the building blocks of programs. The three control
structures are sequence, selection and repetition. The concepts of countercontrolled and sentinel-controlled loops are also introduced.
Selection structures are provided in C via the ‘if’, ‘if-else’, and ‘switch’
statements, as well as the conditional operator. Repetition structures
include the ‘while’, ‘do-while’, and ‘for’ constructs.
Common mistakes in the use of these control structures are
highlighted. Nested structures are also presented.
A good program consists of a well-composed combination of the
various control structures. Hence, programmers have to master this skill
through practice.
166
Chapter 10  Control Structures
Exercises
1.
Declare an integer variable ‘is_letter’ and use it as a flag to indicate if
a character variable ‘ch’ is a letter ('a' to 'z', or 'A' to 'Z'). Write a
program that asks the user to enter a character into ‘ch’, and set
‘is_letter’ accordingly. Then display a message as shown in the two
sample outputs below:
Enter a character: P
'P' is a letter.
Enter a character: ?
'?' is not a letter.
2.
A leap year is one that is divisible by 400. Otherwise, a year that is
divisible by 4 but not by 100 is also a leap years. Other years are not
leap years. For example, years 1912, 2000, and 1980 are leaps years,
but 1835, 1999, and 1900 are not. Write a program that asks for the
year, and assign 1 to the flag ‘leap_year’ if it is a leap year, or 0 if it is
not. Then display a message as shown in the two sample outputs
below:
Enter a year: 1912
1912 is a leap year.
Enter a year: 1835
1835 is not a leap year.
3.
What value is assigned to the character variable ‘grade’ if ‘marks’ is
65 in the following code? What is wrong with this code?
if (marks <= 100
grade = 'A';
else if (marks <
grade = 'B';
else if (marks <
grade = 'C’;
else if (marks <
grade = 'D';
else if (marks <
grade = 'F';
4.
)
80)
70)
60)
50)
For each of the two groups of statements below, give the final value
of x if the initial value of x is 1.
if (x >= 0)
x = x + 1;
else if (x >= 1)
x = x + 2;
if (x >= 0)
x = x + 1;
else if (x >= 1)
x = x + 2;
Chapter 10  Exercises
167
5.
Write a program to asks for a positive integer n. If n is 1, output
“There is 1 apple.”. If n is more than 1, output “There are n apples.”.
Instead of using the ‘if’ construct, use the conditional operator.
6.
The grade assignment code was written using the ‘if-else’ construct
(refer to page 154). How could you write it using the ‘switch’
statement? Can you do some manipulation of the data so that your
‘switch’ statement is leaner?
7.
Find the error in each of the following code segments and explain
how to correct it.
(a)
x = 1;
while (x <= 10);
x++;
}
(b)
for (y = 0.1; y != 1.0; y+= .1)
printf("%f\n", y);
(c)
switch(n) {
case 1:
printf("The number is 1\n");
case 2:
printf("The number is 2\n");
break;
default:
printf("The number is not 1 or 2\n");
}
(d)
The following code should print the values from 1 to 10.
n = 1;
while (n < 10)
printf("%d ", n++);
8.
Write a program that sums a sequence of integers. Assume that the
first integer read with scanf() specifies the number of values remaining
to be entered. Your program should read only one value each time
scanf() is executed. A typical input sequence might be
5 100 200 300 400 500
where the 5 indicates that the subsequent 5 values are to be summed.
9.
Write a program that calculates and prints the average of several
integers. Assume the last value read with scanf() is the sentinel 9999.
(You may hence assume that 9999 is not in the range of valid data
values.) A typical input sequence might be
10 8 11 7 9 9999
indicating that the average of all the values preceding 9999 is to be
calculated.
168
Chapter 10  Control Structures
10. Write a program that finds the smallest of several integers. Assume
that the first value read specified the number of values remaining.
11. Write a program that calculates and prints the sum of the even
integers from 2 to 30.
12. Write a program that calculates and prints the product of the odd
integers from 1 to 15.
13. Write a program to compute the xth power of y, where x is a positive
integer and y a floating-point number. Do not use the pow()
function; use a loop instead.
14. The factorial function is used frequently in probability problems.
The factorial of a positive integer n (written n!) is equal to the
product of the positive integers from 1 to n. Hence, 2! = 2, 3! = 6,
and 4! = 24. By convention, 0! = 1. Write a program that evaluates
the factorials of the integers from 1 to 5. Print the results in tabular
format, as illustrated below. What difficulty might prevent you from
calculating the factorial of 20?
n
-1
2
3
4
5
n!
--1
2
6
24
120
15. Write programs that prints the following patterns. Use ‘for’ loops to
generate the patterns. All asterisks (*) should be printed by a single
printf() statement of the form printf("*");. The last two
patterns require that each line begin with an appropriate number of
blanks.
(A)
(B)
(C)
(D)
*
**
***
****
*****
******
*******
********
********
*******
******
*****
****
***
**
*
********
*******
******
*****
****
***
**
*
*
**
***
****
*****
******
*******
********
16. Calculate the value of  from the infinite series
 = 4 – 4/3 + 4/5 – 4/7 + 4/9 – 4/11 + …
Print a table that show the value of  approximated by 1 term of
this series, by two terms, by three terms, etc. How many terms of
this series do you have to use before you first get 3.14? 3.141?
3.1415? 3.14159?
Chapter 10  Exercises
169
17. Write a simple loop structure to repeatedly print a message, until the
user enters ‘n’ to stop the repeatition. A sample dialogue is given
below.
Hello,
Do you
Hello,
Do you
Hello,
Do you
nice
want
nice
want
nice
want
to
to
to
to
to
to
meet you.
continue? y
meet you.
continue? y
meet you.
continue? n
Can you modify the program so that the message is numbers, as
shown below?
1.
Do
2.
Do
3.
Do
Hello, nice to meet you.
you want to continue? y
Hello, nice to meet you.
you want to continue? y
Hello, nice to meet you.
you want to continue? n
18. Add a loop in the square.c program so that you can repeatedly
compute the square of different numbers. As in question 17, you end
the program by entering ‘n’ to the prompt. Below is a sample
dialogue:
Enter the number to be squared: 5
The square of 5 is 25.
Do you want to try another number? y
Enter the number to be squared: 10
The square of 10 is 100.
Do you want to try another number? y
Enter the number to be squared: 12
The square of 12 is 144.
Do you want to try another number? n
170
Chapter 10  Control Structures
19. Write a program with a menu to provide alternative actions. The
user is shown the menu, and may choose one of the available
options. The example below shows a simple program that displays
different messages:
1. Display 'Hello!'
2. Display 'How are you?'
3. Exit
Enter your choice: 1
Hello!
1. Display 'Hello!'
2. Display 'How are you?'
3. Exit
Enter your choise: 2
How are you?
1. Display 'Hello!'
2. Display 'How are you?'
3. Exit
Enter your choise: 3
20. Write a menu-driven application to ask for two floating-point
numbers, and perform addition, subtraction, multiplication and
division on these two values. The user may choose which operation
he would like by selecting an option on the menu. A sample run is
shown below:
0. Enter 2 values
1. Addition
3. Multiplication
4. Division
Please enter your choice: 0
2. Subtraction
5. Exit
Enter first value: 6.5
Enter second value: 4.1
0. Enter 2 values
1. Addition
3. Multiplication
4. Division
Please enter your choice: 2
2. Subtraction
5. Exit
Result of (6.5 – 4.1): 2.4
0. Enter 2 values
1. Addition
3. Multiplication
4. Division
Please enter your choice:
2. Subtraction
5. Exit
Download