0% found this document useful (0 votes)
11 views85 pages

ITP Week 3

This document covers conditional statements in C programming, focusing on decision-making through if, if-else, and switch statements. It explains the syntax and usage of these statements, including examples of nested if-else structures and switch-case scenarios. Additionally, it includes practice assignments to reinforce the concepts learned about conditional logic and loops.

Uploaded by

asfcsharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views85 pages

ITP Week 3

This document covers conditional statements in C programming, focusing on decision-making through if, if-else, and switch statements. It explains the syntax and usage of these statements, including examples of nested if-else structures and switch-case scenarios. Additionally, it includes practice assignments to reinforce the concepts learned about conditional logic and loops.

Uploaded by

asfcsharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 85

WEEK 3

Reading: Conditional Statements in C


This reading introduces you to branching. You will learn how decision-making can be incorporated into a program. You will
learn to write a program incorporating decision-making using conditional statements, including the if statement, if-else
statement, and switch statement.

Statements and Blocks in C:

Statement: A statement is an expression terminated by a semicolon. A program consists of many such statements.

A statement needs NOT to be an entire line in a program. Whenever a C compiler sees a semicolon (;) in a line, which is not
in a string or in a comment, it considers it as the end of the current statement. Thus, there can be more than one statement
in a single line.

For example:

For the C compiler, there are in total four statements in the above snippet, which are listed as follows:

Statement 1: c = a + b;

Statement 2: i++;

Statement 3: printf(“Hello World”);

Statement 4: 25;

In fact, ‘25;’ is also a statement. It is an expression whose value is True. Since we are not assigning it to a variable or not
doing anything with it, this expression is just ignored by the compiler.

Block: A block in C is a set of statements enclosed inside a set of braces { and }.

A block is also called a compound statement since it consists of one or many statements combined as a single unit.

For example:

Why Block Statements?

Blocks can be used in scenarios where we want to make a decision in a program, and based on the outcome of the decision,
whether True or False, we want to execute a particular block.
Conditional Statements in C: The If Statement

The if statement is one of the simplest conditional statements in C, which helps us make a decision and choose a
corresponding path of action. Branching in C language is primarily done using the if statement.

Syntax:

Condition is an expression in C that is either True or False or it evaluates to either True or False. A Conditional expression
can be written as:

• True or False

• Statement using relational operators such as ==, >= , <=, !=, <, and > Example:

o (x+y >= 10)

o (x == 0)

• Statement using logical operators such as &&, ||, and ! Example:

o (marks >= 90 && marks <= 100)


Note: There is a difference between the relational operator ‘==’ and the assignment operator ‘=’. The ‘==’ operator is used
for comparing equality in a conditional expression that results in either True or False, whereas the ‘=’ operator is used to
assign a value to a variable in assignment statements.

Evaluation or Outcome of a Condition

The outcome of a condition is always one of the following:

• Non-zero or true

• Zero or false

Examples:

Syntax of an if statement:

The statement gets executed only if the condition evaluates to true or non-zero.
The block of statements gets executed only if the condition evaluates to true or non-zero.

Flowchart of an if statement:

Figure 1: Flowchart of an if statement.

Let us take an example of a C program that uses an if statement.

Figure 2: A C program to check if the entered number is positive, using a conditional if statement.

The program in Figure 2 is to check if an entered number is positive. It gets the number in variable ‘a’ from the user and
checks it in a condition in line 6 using an if statement. The conditional statement is ‘(a > 0)’. Whether ‘a’ is greater than 0 or
not. The value of this conditional statement is either True, when ‘a’ is greater than 0, and it is False when ‘a’ is not greater
than 0. This value of the conditional statement decides whether the if statement block will be executed or skipped. The
statements in the block (lines 7 to 9) are executed if the condition is true, otherwise the statements are ignored or skipped.

The program in Figure 1 thus runs differently depending on the entered number. Following are some example cases:

1. If the number is 23 Output: Enter a number 23 Number is positive Rest of the program Program execution:
Variable is initialized at line 3 and the user is prompted to ‘Enter a number’ at line 4. The program waits for the user
to type a number and press Enter. When the user enters 23, at line 5, variable ‘a’ is assigned a new value 25 using
scanf(). The ‘scanf’ is a standard input function provided by the C programming language to take input from the
user and store it at a location corresponding to the address of a variable. Now, with the value stored at the address
of ‘a’ as 23 (that is, a is equal to 23), at line 6, the value of the conditional statement (a > 0) becomes True, since 23
is greater than 0. Thus, program flow enters the block at line 7 and executes the statements sequentially. In this
program, there is only one statement in the block, line 8. After executing the statement in the block and printing
‘Number is positive’, the program flow continues sequentially with the next statements, that is, lines 10 and 11. At
line 10, the program prints ‘Rest of the program’ in a new line and the program exits and stops the execution at line
11.
2. If the number is -20 Output: Enter a number -20 Rest of the program If the user enters the number ‘-20’, the value
of the conditional statement (a > 0) in line 6 becomes ‘False’ since the value stored at the address of ‘a’ is -20 and -
20 is NOT greater than 0. Thus, the program control entirely skips the if statement block (between curly braces,
line 8) and directly executes the next statement in the flow, that is, line 10. Thus, the program prints only ‘Rest of
the program’.
3. If the number is 0 Output: Enter a number 0 Rest of the program Similar to Case II, the input is 0, which is NOT
greater than 0. Hence, the entire if statement block was skipped to print only ‘Rest of the program’.
The If-Else Statement

The if statement without else executes a block only if the condition is true. But the program does nothing if the condition
is false, and the rest of the program is executed.

When we also want to define a statement or block of statements, which should be executed when the condition is false, we
use the optional else clause. The if-else statement executes a block if the condition is true, otherwise executes another
block if the condition is false.

Syntax:

If the condition is true, the program executes only statements in ‘block1’ and not ‘block2’. Otherwise, if the condition is
false, it executes only ‘block2’. The execution flow of ‘rest of the program’ is independent of the if-else statement, and it is
executed as it is in either case.

Nested If-Else Statements

Nested if statement: This is an if statement inside another if statement when there are no else clauses. This occurs in the
following scenarios:
Syntax:

Nested if-else statement: An if-else statement inside the if block or else block of another if-else statement is called a
nested if-else statement. Please note that there can always be an if without an else clause.

Syntax:

Similarly, we can have any number of such nestings, although it may make the code appear bulky.

Example of nested if-else statement

Let us consider a C code snippet of a program to find the largest of three numbers in Figure 3. Let us assume the three
numbers are unique. The program in line 5 stores three integers provided by the user in variables a, b, and c.

First, we check if a is greater than b in line 6. If a is greater than b, this means b is not the largest; either a or c is the largest
number. Whichever of a or c is greater, that number is the largest. To compare between a and c, we put a nested if-else
statement in the if block that is lines 8–11. If now, a is greater than c, this implies a is the largest, thus, print “A”. At line 9,
condition 1 (is a > b?) and condition 2 (is a > c?) both are True. Otherwise, if a is not greater than c, that is, c is greater than
a, then print “C” in line 11 since C is the largest.

If our first condition, if a is greater than b, is False, then else block is executed, that is, in lines 14–19. Here, b is greater
than a, thus, either b or c is the largest. So, we put another nested if-else statement (lines 15–18) but inside the else block
this time, to compare between b or c. If b is greater than c, in line 16, we print “B” as the largest number since b is greater
than both a and c. Otherwise, if b is lesser than c, this implies c is the largest since c has already been established as a
greater number than a. Thus, we print “C” in the else statement of the nested if-else statement in line 18.
Figure 3: A C program to find the largest of three numbers.

Let us consider a = 2, b = 8, and c = 4 as entered numbers of the program in Figure 3.

Program control in line 6 checks is a greater than b? False! 2 is not greater than 8. Thus, control goes directly to the else
part in line 13. Now inside else, it checks is b greater than c? in line 15. Yes! 8 is greater than 4. Thus, the program
successfully prints out B as the largest number. And after line 16, the control goes to line 20 to the “End of the program”.

Output:

Please note that with such usage of nested if-else statements, we ensured that exactly one of the four statements/blocks
would be executed out of line 9 or 11 or 16 or 18. Thus, in such scenarios, branching decision-making or nested if-else
statements can be used.

The Switch Statement

A switch statement is a compact way of writing a multiway decision that tests whether an expression matches one of several
constant integer values and branches accordingly.

Syntax
A switch case statement is used when we want to execute a certain matching statement or block of statements for a
particular integer value, which the expression evaluates to.

• The expression (expr) must evaluate to a constant integer value.

• The ‘case’ keyword is used to match the value of the expression to a statement or block of statement. const-expr
is a constant integral value (not a keyword) that accompanies ‘case’ keyword.

• The ‘break’ keyword is used to stop the execution inside the switch statement block. Once statements inside the
switch block start getting executed pertaining to a case match until a ‘break’ is found, the execution will not stop,
and all the statements will be executed irrespective of their cases. If ‘break’ is not used, the flow would fall through
the next case and execute the statements until the switch statement naturally terminates or a ‘break’ is found.

• The ‘default’ keyword is used to specify statement(s) that need to be executed when there is no case match. There
can only be a limited number of cases that can be written in a switch statement. To handle any other value, which
is not already specified in a case, the ‘default’ keyword is used.

If expr evaluates to const-expr1, statements1 are executed and the ‘break’ is encountered and thus the control comes out
of the switch statement. Otherwise, if expr evaluates to const-expr2, statements2 are executed. If expression evaluates to
a value, which is not specified in any case, then default statements are executed.

Examples

Let us take a few examples of branching in C using switch case statements.

Figure 4: A C snippet to match ‘language’ using a switch case statement.

In Figure 4, the integer value of expression ‘language’ is 10. So, the execution flow will directly jump to case 10. As there is
no case 10 (only case 1, case 2, and case 3 are present), the flow goes to the ‘default’ and prints “Other programming
language” and terminates. Thus, the output is:
Figure 5: A C snippet to match a ‘number’ using a switch case statement.

The code snippet in Figure 5 is a very unusual written switch statement. There are no statements as well as no breaks in
cases 1, 2, 4, and 5. Please note that any case can have 0 or more statements or it may or may not have a ‘break’ statement.
When there is no break, the execution flow keeps on falling through the next cases.

The value of the expression number is 5, so it will directly jump to case 5. Since no statements are there in case 5 and, also,
no break is present, the flow falls through the next case, i.e., case 6, and prints “Four, Five, or Six.” Then, it sees a break in
line 12 and gets out of the statement to termination.

Thus, the output is:

Reading Summary

In this reading, you have learned the following:

• How to interpret and use conditional statements in a C code

• The if-else statement and nested if-else statement

• When and how to use a switch statement for branching in a C program


C Programming Practice Lab1
Assignment Questions:

PracticeLab1_Question1

a) Write a C program that takes three integers as input from the user. Print True when all the three integers
are equal, and False otherwise. Do not use switch statements or loops in your program.

b) Now, modify the above program to print True when none of the three integers entered by the user is
equal to another, and False otherwise.

PracticeLab1_Question2

Write a C program that accepts as inputs the marks obtained by a student in a particular exam and then
prints the description of marks obtained based on the following rules.

>=90 - Extraordinary

>=80 - Very Good

>=65 - Good

>=50 - Average

>=40 - Below Average

else - Fail

It is important to note that the program written in the file has some compile time and runtime errors. You
need to resolve them so that the program works correctly. You can use the below test cases for your
reference.

Testcase1 Testcase2 Testcase3

Input - 65 Input - 15 Input - 49

Output - Good Output - Fail Output - Below Average

Compilation/Execution Steps:

• Open a new terminal by clicking on the menu bar and selecting ->Terminal ->New Terminal
Set the path in the terminal: Type the below command and click Enter. (Refer to the md file in the lab for
more details).

cd Week_3/PracticeLab1/Question1 (Change to Question2 when required)

Compile the C file using the following command in the terminal:

gcc <Filename.c> (Example: gcc Question1.c)

Run the C file using the following command in the terminal once the a.out file is created:

./a.out

Note: Every time you make a change in your program or the filename.c file, it is required to compile the
program again using "gcc filename.c" to reflect that change in your a.out. Otherwise, you will be accessing
an a.out file of the previous version of your code and changes you made will not be reflected in the output.
Reading: Loops and While Loop
Reading Objective:

This reading introduces you to looping. You will learn how repetitive and iterative tasks can be achieved using a while loop.

Loops in C:

Looping is used when we want to repeatedly execute a particular statement or a block of statements a number of times to
solve a problem, which is repetitive in nature. Loops are also called repetitive constructs.

What kind of problems are repetitive in nature?

• To print all numbers from 1 to 500

• Compute the average mark of students in a class of size 100

• Sum all the digits on a positive number (the number can have any number of digits)

In the above problems, loops are very effective in writing the program.

Loops should terminate:

If a loop doesn’t terminate, it will keep on executing (goes into an infinite loop) using resources such as RAM, CPU, storage,
etc. This may result in a runtime error. A loop, thus, should have a finite number of steps.

Figure 1: Example flow of a general loop

For example, in Figure 1, suppose we have a key variable x = 25. In step 2, we check the control expression in line 3 if x
is less than 50. If it is true, then we print the current value of x, incrementing the key variable, x by 1. And we go back to the
beginning of the loop and reevaluate the control expression since we have updated the key variable. Repeat this step until
the condition turns false. If it turns false, go to step 3.

Step 2 is thus a looping step. The conditional statement checks a key variable, and some statements in lines 5, 6, and 7 are
executed repeatedly in the loop until the condition remains true. These statements constitute the body of the loop. The
loop will terminate since the statements in the loop also change the key variable, ‘x,’ increasing it to ultimately make the
condition false.

While Loop in C
‘While’ loops are simple loops that repeat a particular statement or block of statements as long as the control expression
evaluates to True. The structure is similar to the general loop above. There is a key variable, control expression involving
the key variable and body of the loop, which is executed while the expression remains True.

It uses a variable in control expression that is generally defined outside.

Syntax

These statements are executed until exp (a control expression) remains true. Following area few examples of Control
Expressions:

• while (answer == ‘Y’): remain in a loop until the value of the answer variable is true.

• while (count): a variable can also be an expression. Here if the count is an integer, if it is non-zero, a loop is
executed, and if it is zero, the loop is terminated.

• while (5): 5 is always a non-zero; thus, it is always True. Thus, there will be an infinite loop unless there is a
mechanism to come out of the loop, which we will see later in this reading.

• while (base>0 && power>=0): relational sub-expressions joined using a logical AND operator to form a
relational expression.

Example:

Consider a C program snippet in Figure 2 to print numbers till 3 using a while loop construct. In line 1, variable var is
initialized with value 1. This will act as the key variable in our loop. Line 2 starts the while loop, which should run the loop
body until ‘var’ remains less than or equal to 3. The loop body is the block of the statement(s) in curly braces in line 4.

The execution flow enters the loop with the value of var as 1. Since 1 is less than or equal to 3, the control expression is true,
and line 4 is executed. It prints the current value of var, that is, 1, and after executing line 4, the value of var is incremented
by 1 (since we have written var++) to become 2. The control flow loops back to line 2 to again compare the value of var with
3. Since it is 2 that is still less than or equal to 3, the body is executed once again. The current value of the variable is printed,
that is, 2, and its value is incremented by 1 to 3. Again, the condition is checked, which is true since 3 is less than or equal
to 3, and line 4 is executed one last time, printing the value of var, 3, and incrementing it to 4. When the flow loops back to
line 2 to check the condition, it now evaluates to false since 4 is not less than or equal to 3, and the loop terminates.

Figure 2: Snippet using while loop construct to print numbers till 3


Hence the loop is executed 3 times, printing values 1, 2, and 3. Then finally terminates executing line 6. The output of the
above snippet is:

A Null Body

There is a difference between while (num > 0) and while (num > 0);

After a while loop, a statement or block is placed. For example:

But a while loop in C can also have a null body. As we know, any statement in C ends with a semicolon ( ; ). Thus, a
standalone semicolon represents an empty statement. If instead of any statement or block of statements in the body of
the ‘while’ loop, there is just a semicolon, it represents an empty body.

Please note that such empty loops are generally unwanted since they can be infinite. Do NOT put a semicolon after
‘while()’, unless it is intentionally required.

The loop will still run, use up, and waste computer resources, but in each iteration, it does nothing. And if the loop is started,
it will most probably never terminate since the condition for which the loop started remains true, and the key variable is
not modified in any iteration.

Example1 of a While Loop

To write a program to calculate the sum of the first N positive integers, you may define the value of N using a pre-processor
directive.

Figure 3: A C program to calculate the sum of the first N positive integers

Refer to the C program in Figure 3. In line 6, a while loop is placed, which is used to find the sum of N numbers and store it
in the variable ‘sum’, which is initially set to 0. We are counting from 1 to number N using the variable ‘index’ and adding
the value of the current number (index) at each step, updating the new sum in variable ‘sum’. In each step, the control
variable, index, is incremented by 1, and the loop will terminate when the index becomes greater than N. Thus, after N
steps,the loop terminates with the final and desired sum.

Line 9 could also be written as,

or

Line 11 is out of the while loop and will be executed just after the loop breaks. The loop is terminated when the variable
‘index’ becomes just greater than N, that is, N+1. Hence, the output of the program is:

Let us take a look at the value of variables in each iteration of the while loop in this program:

But what if we wanted the sum of the first 100 positive integers instead of 10? or 50? In an already written program, you can
simply change the value of ‘N’ in line 2 and run the program to get quick results. Following are a few examples with different
values of ‘N’:

Example 2 of a While Loop

Let us write a C program to ensure that the user enters a positive integer. That is:

• Every time a negative number or a zero is input, it gives an appropriate message

• Once a positive integer is entered, it prints the square of that number.

So, the program should keep on asking the user to input a positive number until the user inputs such a number. This
implies the usage of a loop in code. Now, we will use a while loop, as seen in the program in Figure 4.

The user enters a number for the first time in line 6. It is checked in line 7 if the number is positive before entering the loop.
If it is positive, do not enter the loop and print its square in line 12. But if it is a negative number, enter the loop, and ask for
the number again. Since the number itself is in the condition as a key variable, the loop will keep on asking for input (using
scanf) until a positive number is seen. And whenever a positive number is entered, the loop terminates, and the program
prints its square.
Figure 4: A C program to print the square of an input number, ensuring the user enters a positive number

The output of the program with certain inputs is:

‘While’ loop is very important in this scenario since we don’t know how many times the loop may run. Depending on the
user’s input, it may run 0 or 100, or countless times.

Nested While Loops

A while loop within a while loop is called a nested while loop. Following is the simplest syntax of a nested while loop:

Let’s take a look at one such example.

Example of a Nested While Loop


Assume there are N students in a class, and we want a C program to compute the average marks obtained by each student
in his/her three subjects. Thus, the program should take as input three subject scores for each student and print the average
marks obtained by each student.

Refer to the program in Figure 5. There are two loops, one outer and one inner. The outer loop in line 6 is to iterate over N
students, and for each student, there is the inner loop in line 11 to iterate over their subjects. Thus, the inner loop will run
3 times corresponding to the three subjects. The key variables are incremented to make sure the loops do not run infinitely.
For the outer loop, the key variable ‘index’ is incremented in line 21, which is the last line of the body of the outer ‘while’.
And for the inner loop ‘j’ is incremented in line 16, which is the last line of the body of the inner while.

Figure 5: A C program to compute the average marks of each student using a Nested While Loop

The following is a sample output of the program:


The Break and Continue Statements

We have seen a loop running for N iterations. But what if we decide in one of those iterations that we want to skip that
iteration or come out of the loop entirely? These are made possible with the help of continue and break statements.

• break: It forces control to come out of the immediately enclosing loop. We have already seen that the break
statement is used to come out of the Switch statement as well.

• continue: It skips the subsequent statements in the body of the immediately enclosing loop and proceeds to its
next iteration.

Example

Let us consider an example of writing a program to calculate the sum of positive numbers entered by the user such that:

• When a negative value is entered, ignore it; prompt the user to enter a positive integer.

• When zero is entered, terminate the loop, and finally,

• Display the sum of the positive numbers entered by the user.

Refer to the program code in Figure 6 that solves this problem and uses break and continue statements.

In line 6, we start an infinite loop since 1 means always true. But we don’t want an infinite loop; thus, we will use ‘break’ to
come out of the loop when 0 is entered. Thus, the program terminates the loop, prints the sum in line 16, and immediately
stops as soon as the user enters 0.
Figure 6: A C program to find the sum of all input positive numbers until 0 is entered

If a user enters any negative number, the condition in line 10 becomes true, and the ‘continue’ statement is executed. The
continue statement skips the rest of the loop in that iteration. Hence, lines 12 to 14 are not executed (and the sum is not
updated) when the user enters a negative number.

The following is a sample output of the execution of the program:

The user entered only three positive numbers: 1, 2, and 3, and the program printed the sum as 6, ignoring/skipping the
iterations with negative numbers and terminating as soon as the user entered 0.

Reading Summary

In this reading, you have learned the following:

• What is meant by a while loop, how it operates, and when to use it

• How to write a simple, compact program using a while loop

• The power of a while loop is that it can be used when the number of iterations is not known

• How to use the nested while loops


• How and when to use the continue and break statements within a loop
C Programming Practice Lab2
Assignment Brief:

Practice Lab 2_Question 1

1. Please find the output of a C program intended to print a pattern using integers. The pattern has N
rows, where N is input from the user. The first row begins with the number N and prints all numbers
from N to 1 in decreasing order. The second row starts with the number N-1, and so on. The last row
has the single number 1. The following is the inverted right triangle pattern for N=5:

The program provided in the file has a semantic error, and it is printing the following pattern for N = 5:

Semantic error is different from syntactic error. It means the C code will successfully compile without error
but will not produce the intended results. Modify the provided code to rectify the logical error.

2. Modify the program slightly to print the following pattern as well:

Practice Lab 2_Question 2

Use a While loop to write C programs that enable the user to enter a number and keep entering till

1. A positive number is entered

2. A negative number is entered

3. The number is either greater than 5 or less than -5

4. The number is greater than 20 and less than 100


[Note: Please use multi-line comment to comment out the previous subpart while doing the second subpart
onwards.]

Practice Lab 2_Question 3

Write a program to verify the Collatz conjecture. Here, the Collatz conjecture is asking whether repeating
two simple arithmetic operations will eventually transform every positive integer into 1. Consider the
following two operations:

When the number is odd:

f(odd) = 3*odd + 1

When the number is even:

f(even) = even/2

With these two transformations, any number should ultimately reach 1. For example, taking 10 will generate
the following series till 1:

10 5 16 8 4 2 1

This is just a conjecture and not a theorem. You need to verify if all the numbers from 1 to 1000000 follow
this conjecture. Write a program that loops through numbers from 1 to N, and then for each number, it loops
with either of the two operations until number 1 is seen.

If the loop runs infinitely, it means that the conjecture is not holding correctly for that number yet.

[Hint: Explore long long or unsigned long long data types for variable declaration.]

PracticeLab 2_Question_4

a) Complete the C program using a switch case to print the month's name for a corresponding integer the
user enters. The program has to ensure that the user enters integers only from 1 to 12. Consider the
following sample inputs and outputs:

Testcase1 Testcase2 Testcase3 Testcase4

Input - 13

Input - (-1)
Input - 3 Input - 11 Input - 2
Input - 16
Output - March Output - November Output - February
Input - 2

Output - February

b) Modify the above program to print all the months till December, starting from the month corresponding
to the integer input.
Testcase

Input - 9

Output - September

October

November

December
Reading: For Loop
Reading Objective:

In this reading, you will be introduced to the for loop in C and the various parts of a for loop. You will learn the ways to use
a for loop and how it is different from a while loop.

Main Reading Section:

For loop is a powerful iterative construct defined in C. The structure of a for loop is as follows:

Fig 1: Structure of a For Loop

A for loop consists of 4 parts:

1. Initialization

a. This part of the for loop is highlighted in red in Fig 1.

b. The initialization part of the for loop is executed exactly once, and it is when the for loop starts executing
for the first time.

c. Usually, it is used to initialize variables meant to count the number of iterations for which the for loop has
been executed.

d. It is worth noting that any variable declared inside the initialization part (or the body) of the for loop will
be deleted when the for loop exits (You will learn more about why this happens in Week 4, Lesson 2). Hence,
do not declare the variables that store the result of your computation inside the initialization of the for
loop.

2. Condition

a. This part of the for loop is highlighted in blue in Fig 1.

b. The condition part of the for loop is either blank or contains a Boolean expression. This expression is
evaluated after every iteration of the loop. If it is True, the loop is executed once again, and if it is False,
then the loop is terminated.

c. When the condition is left blank, the compiler interprets it as True, and thus, the loop is executed infinitely.

d. We can use logical or relational operators to make the condition part of the for loop.

3. Increment/Decrement

a. This part of the for loop is highlighted in gold/yellow in Fig 1.

b. It is executed after every iteration of the for loop, i.e., if the condition is True, the body of the loop is
executed, and after that, this variable’s value is incremented/decremented, and it is this new value used
for the next check with the condition. Usually, it is used to increment/decrement the value of the counter
variable.

4. Body of the for Loop


a. This part of the for loop is highlighted in grey in Fig 1.

b. This is the single statement or the block of statements that comes just after the for loop statement and is
executed repeatedly by the for loop as long as the condition holds true.

The Flow of Execution of the For Loop

The flow of execution of the for loop can be understood very easily from the flow chart in Fig 2.

Fig 2: Flow Chart Showing Execution of a For Loop

Firstly, the initialization part of the for loop is executed(usually initializing value to a variable). Then the condition is
evaluated to be True or False. If the condition is False, the loop is terminated. If the condition is True, then the body of the
loop is executed, and then the increment/decrement statement is executed. Then the condition is evaluated again, and
this continues until the condition finally evaluates to False.

Let’s see how the execution of the above program happens step by step.

1. Firstly, the variable i is declared in line 3, and its value is some garbage value.

2. Then the initialization statement in the for loop is executed, and the value of i becomes 1.

3. The condition statement is executed, i<=3 is checked, which evaluates to True because i = 1.

4. Now, the printf statement is executed, 1 is printed on the screen.

5. The increment statement is executed, i++, and the value of i becomes 2.

6. The condition statement is executed, i<=3 is checked, which evaluates to True because i = 2.

7. Now, the printf statement is executed, 2 is printed on the screen.


8. The increment statement is executed, i++, and the value of i becomes 3.

9. The condition statement is executed, i<=3 is checked, which evaluates to True because i = 3

10. Now, the printf statement is executed, 3 is printed on the screen.

11. The increment statement is executed, i++, and the value of i becomes 4.

12. Condition statement is executed, i<=3 is checked, which evaluates to False because i = 4

13. The loop terminates, and return 0 is executed, which terminates the entire program.

The output of the program is

In the above example, there is only one statement inside the for loop, so we can omit the use of curly brackets around that
statement and rewrite the above code as shown below.

However, if we happen to mistakenly add the return 0 statement inside the for loop, as shown below, then the execution
will be different, as explained below.

The steps of execution of the above program are as follows:

1. Firstly, the variable i is declared in line 3, and its value is some garbage value.

2. Then the initialization statement in the for loop is executed, and the value of i becomes 1.

3. The condition statement is executed, i<=3 is checked, which evaluates to True because i = 1.

4. Now, the printf statement is executed, 1 is printed on the screen

5. return 0 is executed and the entire program terminates.

The output of the program is


There is nothing right or wrong in using return 0 inside the for loop. It’s important that we understand that using return 0
inside the for loop would completely change how the program executes.

Various Forms of For Loop

There are some variations that we can do in a for loop. These are discussed below:

1. We can change the increment for the counter to any value in the increment statement. In fact, we can declare/initialize
multiple variables inside the for loop and increment/decrement multiple variables inside the increment section of the for
loop.

The following code is also correct

2. Instead of declaring the counter variable inside the for loop, we can declare it outside the loop also as shown below.
When the variable is declared outside the loop, the variable still exists after the termination of the loop, whereas if we had
declared the variable inside the initialization statement of the for loop, then the variable would have been deleted after the
termination of the loop.

3. Instead of incrementing the counter in the increment/decrement part of the for loop, we can also increment/decrement
the counter variable inside the body of the for loop.

4. We can omit either or all the 3 parts of the for loop, i.e., initialization, condition, and increment/decrement of the for
loop. For example, the below code executes an infinite loop.

5. We can also put an empty statement as the only statement in the body of the for loop. For example, the below code
consists of an empty statement in the body of the loop.
Examples of For Loops

Example 1: Print the sum of the first N odd numbers.

In the above program, the variable i is used for iterating over all natural numbers, the variable sum is used to store the sum
of odd numbers, and the counter variable count is used to store how many odd numbers have already been visited. We
make the loop execute for the value of i = 1, then 2, then 3, then 4, and so on. In case i is even, we skip that iteration of the
loop using a continue statement. Else, we add i to the sum variable and increment the count variable. When the count
becomes equal to N, we break out of the loop.
Note: When the continue statement is executed inside a for loop, the control resumes execution from the
increment/decrement step of the for loop. Break statement in for loop works similarly to break statement in while loop,
both terminate the loop and resume program execution from the next statement after the loop.

Example 2: Write a C program using a for loop to print the sum of all numbers from 1 to 1000 (including both 1
and 1000), which are multiples of 3 but not multiples of 4.

In the above program, we iterate over all the numbers from 1 to 1000. For each number, we check whether it is a multiple
of 3, and not a multiple of 4. If yes, it is added to the final sum. At last, we print the value of the sum.

Example 3: Write a C program to print the following pattern using for loops:

* *

* * *

* * * *

* * * * *

Take the value of N (the number of rows in the pattern) as input from the user.
In the above program, we take input from the user in a variable n. Then we declare two variables, i_row and i_col, to store
the index of the current row and column in which we are printing the pattern. We iterate over the number of rows using the
i_row variable. In each row, we print stars equal to the index of the row using the i_col variable, and then we print a new
line character. Note that the printf statement in line 9 is the only statement in the body of the for loop in line 8, and the for
loop in line 7 contains lines 8–10 in its body. The above code is an example of a nested for loop. The key takeaway should
be that the outer loop gets initialized first, then the condition is checked, and if it is True, program control goes into the
body of the loop. In this case, the body has another inner for loop, which again does its own initialization and checks its
condition. If the condition is True, it keeps executing the body of the inner loop as long as its condition remains True. Once
it becomes False, it comes out of the inner for loop, and now only the increment happens to the outer for loop, again checks
the condition and gives control to the inner for loop, and this continues until the outer for loop condition becomes false.

While vs. For Loop

Writing for loop in the form of a while loop

for loop

while loop

Fig 3: How to write a for loop in the form of a while loop

Writing while loop in the form of for loop


while loop

for loop

Fig 4: How to write a while loop in the form of a for loop

Figures 3 and 4 show how easy it is to write a for loop as a while loop, and a while loop as a for loop. But still, the structure
of both the loops is such that it is preferred to use the for loop when we already know the number of iterations for which
the loop will be executed, and the while loop is preferred when we do not have a fixed number of iterations of the loop, we
only have a termination condition. For example, if we want to keep asking the user to enter an integer till he/she enters a
valid integer, we have a termination condition, i.e., the user enters a valid integer, but there is no fixed number of iterations
of the loop, so we use a while loop. Whereas, to find the sum of the first N odd numbers, we know the number of iterations
of the loop, so we use a for loop.

Try to execute all the programs discussed in this reading in Coursera labs. You will learn best when you try to write and
execute these programs yourself.

Reading Summary:

In this reading, you have learned the following:

• The structure of a for loop and the flow of its execution

• How to write initialize, condition, and increment/decrement statements in a for loop

• Write programs using various forms of the for loop

• How to choose between a while and for loop for a given problem
C Programming Practice Lab3
Assignment Questions:

Practice Lab 3_Question 1

1. Compile a C program using the file included along with this question. The file contains a C program
that is intended to take a natural number as input from the user and print the sum of squares from
1 to N.

Please note that upon compiling this program, the compiler shows some errors. You need to resolve the
errors and successfully compile the program. You can check whether the program has successfully
compiled by testing it over the following test cases.

Testcase 1 Testcase 2 Testcase 3


Input – 10 Input – 17 Input – 100
Output – 385 Output – 1785 Output – 338350
b) Now, copy the above program into a new file named sum_of_cubes.c, and try to modify it to print the
sum of cubes from 1 to N.

Practice Lab 3_Question 2

The C program file attached with this question compiles successfully. Upon execution, the program enables
the user to enter a positive number and then prints some numbers before terminating.

Go through the program and find out the functionality of the above program. Pay special attention to the
use of continue and break statements inside the for loop and explore the use of these statements.

Practice Lab 3_Question 3

1. The C program in the file attached to this question intends to print an alternating pattern of 1’s and
0’s, based on the number of rows entered by the user as follows:

101010……

010101……

…………….

…………….

where the number entered by the user is the number of rows and columns to be printed in the pattern. Fill
in the blanks A, B, C, and D with appropriate expressions so that the program works correctly. Consider the
following test cases for your reference.

Testcase 1 Testcase 2

Input - 5
Input - 2
Output - 10101
Output - 10
01010
01
10101
Testcase 1 Testcase 2

01010

10101

2. Now, change what you entered in the blanks A, B, C, and D, so that the program prints a triangle of
alternating 0’s and 1’s instead of a square. Consider the following test cases for your reference.

Testcase 1 Testcase 2

Input - 5

Input - 3 Output -1

Output - 1 01

01 101

101 0101

10101

Practice Lab 3_Question 4

Write a C program that takes two positive numbers, a and b, as input from the user. If either of the numbers
is less than or equal to zero, then terminate the program there itself. Use a for loop to print the value of a
raised to the power b, that is, abab.

Below are some test cases for your reference. You can use the C program file attached with this question as
a template. The variables in this program are declared with unsigned long long int datatype because when
performing power operation, the result can be more than the maximum limit of value that an int variable
can store in C.

Testcase 1 Testcase 2 Testcase3

Input - 2 3 Input - 3 2 Input - 3 4

Output - 8 Output - 9 Output - 81


Solutions to the Practice Labs
PracticeLab1_Question1(a)
#include<stdio.h>
int main(){
int a, b, c;
printf("Enter three integers a, b, and c - ");
scanf(" %d %d %d",&a,&b,&c);

if(a==b){
if(a==c){

printf("True\n");
}
else{
printf("False\n");
}
}
else{

printf("False\n");
}

/*
//alternate soln
if(a==b && a==c){
printf("True\n");
}
else{
printf("False\n");
}
*/

return 0;
}
PracticeLab1_Question1(b)
#include<stdio.h>
int main(){
int a, b, c;
printf("Enter three integers a, b, and c - ");
scanf(" %d %d %d",&a,&b,&c);

if(a!=b && a!=c && b!=c){ printf("True\n");

}
else{
printf("False\n");
}

/*
//alternate soln
if(a==b)
printf("False\n");
if(a==c)
printf("False\n");
if(b==c)
printf("False\n");
else

printf("True\n");
*/

return 0;
}
PracticeLab1_Question2
#include<stdio.h>

int main(){

int marks;
printf("Please enter your marks: ");

scanf(" %d", &marks);

if(marks >=90)
printf("Your grade is Extraordinary");

else if(marks >=80)

printf("Your grade is Very Good");

else if(marks >=65) printf("Your


grade is Good");

else if(marks >=50)

printf("Your grade is Average");

else if(marks >=40)

printf("Your grade is Below Average"); else

printf("Fail, but it is not the end of the world.");

Practice Lab 2_Question 1-(1)part


#include<stdio.h>
int main()
{
/*
Current wrong output:
1
21
321
4321
54321

Intended Output, part a:


54321
4321
321
21
1
*/
int N;
printf("Enter a Number N: ");
scanf(" %d", &N);

int i = 1; // outer loop control variable


int j; // inner loop control variable
while(i <= N)
{
j = N-i+1;
while(j > 0)
{
printf("%d",j);
j--;
}
i++;
printf("\n");
}
}
Practice Lab 2_Question 1-(2)part
#include<stdio.h>
int main()
{
/*
part b
Intended Output:
54321
5432
543
54
5
*/
int N;
printf("Enter a Number N: "); scanf("
%d", &N);

i = 1; // outer loop control variable


while(i <= N)
{
j = N;
while(j >= i)
{
printf("%d",j);
j--;
}
i++;
printf("\n");
}
}
Practice Lab 2_Question 2
#include<stdio.h>
int main()
{

int N;
printf("Please Enter a number greater than 0: ");
scanf(" %d", &N);

while( N<=0)
{
printf("Please Enter a number greater than 0: ");
scanf(" %d", &N);
}
printf("Ok, number entered is greater than 0");

printf("\nPlease Enter a number lesser than 0: ");


scanf(" %d", &N);
while( N>=0)
{
printf("Please Enter a number lesser than 0: ");
scanf(" %d", &N);
}
printf("Ok, number entered is lesser than 0\n");

printf("\nPlease Enter a number greater than 5 OR less than -5: ");


scanf(" %d", &N);
while( N<=5 && N>=-5)
{ printf("Please Enter a number greater than 5 OR less than -5: ");

scanf(" %d", &N);


}
printf("Ok, number entered is greater than 5 OR less than -5\n");

printf("Please Enter a number greater than 20 AND less than 100: ");
scanf(" %d", &N);
while( N<=20 || N>=100)

{
printf("Please Enter a number greater than 20 AND less than 100:
");

scanf(" %d", &N);

printf("Ok, number entered is greater than 20 AND less than 100\n");

return 0;
}
Practice Lab 2_Question 3
#include<stdio.h>
int main(){

int end = 1000000; // 1. Try smaller number


int start = 1;
unsigned long long i = start, j = 0; // 2. Should we use just int here
if 'end' is too large ? Change datatype as mentioned in the ques

while(i <= end){

j = i;
// printf("%llu ", j); //uncomment if you want to see the series
// loop until the current number becomes 1
while(j!=1)
{

if(j%2 == 0){
j/=2;
}

else{
j = 3*j +1;
}

// printf("%llu ", j); //uncomment if you want to see the


series
}

// %d id for int, explore %llu


// printf("\n%llu \n\n", i);
printf("%llu ", i);
i++;
}
return 0;
}
PracticeLab 2_Question_4 (a)
#include<stdio.h>

int main(){

int month_number; // 1 to 12

printf("Please enter month number between 1 and 12: "); scanf("


%d", &month_number);

while(month_number <1 || month_number>12){

printf("Please enter Correct month number between 1 and 12: ");

scanf(" %d", &month_number);

switch(month_number){ case 1:
printf("January"); break;

case 2: printf("February"); break;

case 3: printf("March"); break;

case 4: printf("April"); break;

case 5: printf("May"); break;

case 6: printf("June"); break;

case 7: printf("July"); break; case


8: printf("August"); break;

case 9: printf("September"); break;

case 10: printf("October"); break;

case 11: printf("November"); break;

case 12: printf("December"); break;


}

return 0;

PracticeLab 2_Question_4 (b)


#include<stdio.h>

/*

sample inputs and outputs

input: 9

output: September

October

November
December

*/

int main(){

int month_number; // 1 to 12

printf("Please enter month number between 1 and 12: ");


scanf(" %d", &month_number);

while(month_number <1 || month_number>12){

printf("Please enter Correct month number between 1 and 12: ");

scanf(" %d", &month_number);

switch(month_number){
case 1: printf("January\n");
case 2: printf("February\n");

case 3: printf("March\n");

case 4: printf("April\n");

case 5: printf("May\n");

case 6: printf("June\n");
case 7: printf("July\n");

case 8: printf("August\n");

case 9: printf("September\n");

case 10: printf("October\n");

case 11: printf("November\n");

case 12: printf("December\n");

return 0;

Practice Lab 3_Question 1 (a)


#include<stdio.h>

int main(){

int N;

printf("Enter the value of N - ");

scanf(" %d", &N);

int sum = 0;

for(int i = 1; i<=N; ++i){

sum += i*i;

}
printf("Sum of squares from 1 to %d is %d\n", N, sum);

return 0;

Practice Lab 3_Question 1 (b)


#include<stdio.h>
int main(){

int N;
printf("Enter the value of N - ");
scanf(" %d", &N);

int sum = 0;

for(int i = 1; i<=N; ++i){


sum += i*i*i;
}

printf("Sum of cubes from 1 to %d is %d\n", N, sum);

return 0;
}
Practice Lab 3_Question 2
The program prompt asks the user to enter a positive number (although it doesn’t throw an error
if zero or a negative number is entered). Then if the number is greater than or equal to 79, it
simply exits. If number entered is less than 79 (even a negative number), the program prints all
the multiples of 5 in the range (start,79). ‘Start’ will be printed only if it is a multiple of 5
otherwise the next immediate multiple of 5 coming after 5 will be printed, similarly at the end as
last number 75 is printed which is the last multiple of 5 before 79.
#include<stdio.h>

int main(){

int num_rows;

printf("Enter the number of rows for which the pattern should be

printed - ");

scanf(" %d", &num_rows);

for(int i = 1; i<=num_rows ;++i){


for(int j = 1;j<=i; ++j){

printf("%d",(i+j+1)%2);

Practice Lab 3_Question 3 (1)


#include<stdio.h>
int main(){

int num_rows;

printf("Enter the number of rows for which the pattern should be

printed - ");

scanf(" %d", &num_rows);

for(int i = 1; i<=num_rows ;++i){ for(int


j = 1;j<=num_rows; ++j){

printf("%d",(i+j+1)%2);

printf("\n");

printf("\n");

return 0;
}

Practice Lab 3_Question 3 (2)


printf("\n");

printf("\n");

return 0;
}
Practice Lab 3_Question 4

#include<stdio.h>

int main(){

unsigned long long int a, b, ans = 1;


// Variables are declared as unsigned long long int so that they can

store big integers also

printf("Enter two positive integers a and b - ");

/* ENTER A STATEMENT TO TAKE a AND b AS INPUT FROM THE USER HERE*/


scanf(" %llu %llu", &a, &b);

/*WRITE A FOR LOOP TO MULTIPLY ans BY a FOR b NUMBER OF TIMES*/

for(unsigned long long int i = 1; i<=b; ++i)

ans *= a;

printf("%llu^%llu = %llu\n",a,b,ans);

return 0;

}
Control Structures—
7 Decision Making
Chapter 7, Sections 7.1-7.7, 7.10, 7.12, and 7.15.

WHAT TO LEARN

Significance of the control expression for making decisions.


Use of the if-else construct for two-way decision making.
Nesting of if-else constructs for multi-way decision making.
Indentation and pairing issues with nested constructs.
Using a conditional expression for simple two-way decisions.
Usefulness of the switch construct for testing equality.
Whether the goto statement deserves the ill-reputation that it has acquired.

7.1 DECISION-MAKING CONCEPTS


We are frequently confronted with the need to make a decision on what to do next. Decisions
enable devices or applications to behave in different ways depending on the data they encounter.
A decision can be two-way or multi-way, and one decision can lead to further decision making.
Here are some real-life situations that involve making decisions:
Blocking access to an ATM when a user fails to enter correct PIN in three attempts.
Switching off the geyser when the required temperature has been attained.
Setting the motor speed of a washing machine depending on the type of wash chosen.
Checking the residual battery charge of a cellphone to activate a notification LED.
All programming languages support at least one construct that supports selection, i.e., decision
making. This construct specifies what to do if one or more conditions are met, and also what to
do otherwise. Complex situations are handled by chaining together a number of such constructs.
As noted before, sequence, selection and repetition can solve any problem that is capable of being
described unambiguously.
208 Computer Fundamentals & C Programming

Execution of a decision-making construct interrupts the default sequential flow of program


execution. It causes control to branch to a different point in the program from where it should return
to resume execution from the next statement. This may not happen if this transfer of control is
caused by improper use of the GOTO statement. Structured programs, therefore, invoke procedures
or functions from where the return is automatic.

7.2 DECISION MAKING IN C


The C language recognizes that, depending on the nature and complexity, different situations need
different decision-making tools to handle them. Consequently, C addresses selection issues with
the following three constructs:
The if statement supported by the optional else keyword.
The switch statement.
The conditional operator (6.17).
The if-else construct, which is common to all languages, takes up most of the chapter space.
The construct handles complex decisions by combining a number of simple if-else constructs.
In certain situations, the switch is better suited for multi-way decision making. The conditional
operator (?:) uses one-liners to handle very simple tasks. You have seen it used in Section 6.17.
7.2.1 The Control Expression
Some C constructs like the if-else and while statements use the true or false value of a control
expression to determine control flow (6.15.1). They require this expression to be enclosed by
parentheses. The control expression is normally a relational or logical expression as shown by the
following examples:
if (amount > 20000)
if (answer == ‘Y’)
if (age >= 60 && sex == ‘F’)
But a control expression can also be any expression that returns any value including 0.
Also, because any non-zero value is true in C, the following expressions are also valid even if they
are neither relational nor logical:
if (total) True if total is greater than 0.
if (count++) True if count is greater than 0 before postfixing.
if (5) Always true.
When framing these expressions, you need to know the relative precedence and associativity of their
operators. Although discussed before, an essential subset of these operators is presented here for
quick reference (Table 7.1). Even though the % doesn’t belong to this subset, it has been included
because it appears in some of the programs in this chapter. The operators are arranged in decreasing
order of their precedence.
Note: The relational operators have a higher precedence than the logical ones. Also remember that
the AND operation is performed before OR.
Control Structures—Decision Making 209

TABLE 7.1 Operators Used for Decision Making (in order of precedence)
Operator(s) Signi cance Associativity
! Logical NOT R-L
% Modulus L-R
<, <=, >, >= Relational L-R
==, != Relational (Equality) L-R
&& Logical AND L-R
|| Logical OR L-R
?: (ternary operator) Conditional R-L

7.2.2 Compound Statement or Block


When using constructs like if and while, you’ll need to address a group of statements as a single
unit. This unit, which is flanked on either side by a matched pair of curly braces, is called a compound
statement. It is also known as a control block, or, simply, block. Here’s a compound statement drawn
from Section 6.5:
if ((last_number % 2) == 1) { Control block begins
printf(“Not an even number\n”);
return 0;
} Control block ends
The printf and return statements form a compound statement which is manipulated by if as
a single statement. Whenever two or more statements are affected by a control expression, they must
be enclosed in curly braces to form a compound statement. It is also permissible to use a compound
statement wherever a single statement is allowed. That is sometimes done to provide clarity.
It could be helpful to keep in mind that a block changes the scope (i.e. visibility) of a variable declared
inside it. Such a variable is not visible outside the block or in other blocks. These visibility issues
will be addressed in Chapter 11.

7.3 THE if STATEMENT


The if statement is the most commonly used selection construct in any programming language.
It has basically two forms—with and without the else keyword. The other forms discussed later
are derived from these two forms. The first form (Fig. 7.1) specifies the action if expression evaluates
to true. The syntax shows the usage for both simple and compound statements.

if (expression is true) if (expression is true) {


statement; statement1;
statement2;
...
}

FIGURE 7.1 The if Statement (Form 1)


210 Computer Fundamentals & C Programming

Execution of this statement begins by evaluating expression. If this value is true, then one or more
statements are executed. Curly braces are not required for a single statement but they are needed
for a compound statement. Here’s a simple example:
if (hours_left > 6) if syntax requires use of parentheses
rate = 25; Next statement should be indented
printf(“Refund amount = %f\n”, rate * amount);
Here, 25 is assigned to rate if hours_left is greater than 6. Note that the printf statement is
executed unconditionally and has nothing to do with the binary outcome of the control expression.
The difference in indentation reveals our true intention and is consistent with what the compiler
also sees.
A compound statement needs curly braces at its two ends. The following compound statement
comprises three simple ones:
if (amount > 10000) {
printf(“You can’t withdraw more than 10000 with this debit card\n”);
printf(“Key in an amount not exceeding 10000\n”);
scanf(“%d”, &amount); if ends at this ;
}
Note there is no semicolon following the } symbol. In the absence of curly braces, only the first
printf would have been executed conditionally.

Note: When used with a single statement, if ends at the semicolon used as statement terminator.
For a compound statement, if ends at the terminating ; of the last statement.

Caution: All control expressions used by the decision-making and loop constructs must be enclosed
within parentheses. The compiler will generate an error if you use if count > 0 or
while count++ <= MAX_COUNT.

7.4 average_integers.c: AVERAGE CALCULATING PROGRAM


Our first program (Program 7.1) calculates the average of two non-zero integers keyed in by a user,
but considers only their absolute values after validation. This means that the - sign is stripped off
from a negative integer. The task has been achieved by using one relational (<) and one logical
operator (||). The program is run thrice.
The program first assigns two integer variables, inta and intb, with input from the keyboard.
It then uses a logical expression as the control expression for if to find out if either of the integers is
zero. It’s good programming practice to first handle those situations that lead to errors. If program
flow moves beyond the first if statement, it means that we have two valid integers in our hands.
Once the validation test has been cleared successfully, the next step is to use two if statements to
compute the absolute values of the two integers. The simplest way to do that is to use the unary
- operator, which simply multiplies its operand by -1. We use the (float) cast to compute the
average of these two integers, because without it, the division would result in truncation of the
fractional part.
Control Structures—Decision Making 211

/* average_integers.c: Calculates average of the absolute values of two


integers. Quits program if one integer is zero. */
#include <stdio.h>
int main(void)
{
int inta, intb;
printf(“Enter two non-zero integers: “);
scanf(“%d %d”, &inta, &intb);
if (inta == 0 || intb == 0) {
printf(“At least one integer is zero\n”);
return 1; /* Good to return nonzero for invalid entry */
}
/* Assigning absolute values to inta and intb */
if (inta < 0)
inta = -inta; /* Using the - unary operator */
if (intb < 0)
intb = -intb;
/* If we have come here, both inta and intb must be positive */
printf(“Average of absolute value of the integers = %.2f\n”,
(float) (inta + intb) / 2);
return 0;
}

PROGRAM 7.1: average_integers.c


Enter two non-zero integers: 7 0 First invocation
At least one integer is zero
Enter two non-zero integers: 5 10 Second invocation
Average of absolute value of the integers = 7.50
Enter two non-zero integers: -13 8 Third invocation
Average of absolute value of the integers = 10.50

PROGRAM OUTPUT: average_integers.c


This program features two return statements, and interestingly, the first one returns the value 1
instead of 0. Does returning 1 instead of 0 make any difference? Yes, it does but only if the next
program takes advantage of this value. It will take a while before you work with cooperative programs,
but it’s good to know that this is the way return was designed to be used (see Inset—How It Works).
Note that we didn’t use separate validation routines for the two integers inta and intb. Instead,
we used the following logical expression:
if (inta == 0 || intb == 0)
This is acceptable for this introductory program since we don’t need to know, in the event of
failure, who the offender is. Sometimes, we need to pinpoint the cause of failure, in which case
you need to use two relational expressions with individual if statements (as if (int a == 0) and
if (intb == 0)), and specify separate paths for each of them.
212 Computer Fundamentals & C Programming

HOW IT WORKS: Why return 1 instead of return 0?


The return statement, when placed in the body of main, terminates a program and transmits
a value to its caller. The caller in most cases is the operating system which saves this value until the
next program is run. In applications comprising multiple programs that depend on one another, it
is often necessary for one program to know whether a previous program has completed successful
execution. The return value provides this information. On operating systems like UNIX and
Linux, a return value of 0 signifies success. On these systems, a programmer uses a non-zero
value with return to indicate failure!

7.5 if-else: TWO-WAY BRANCHING


None of the if statements of the previous program, average_integers.c, explicitly specifies the action
to take when its control expression evaluates to false. The default action is to proceed sequentially
and move on to the next statement following the if statement. The second form of the if construct
permits two-way branching using the else keyword (Fig. 7.2). The statements following else are
executed when the control expression fails.

if (expression is true) if (expression is true) {


statement; statements;
else ...
statement; }
else {
statements;
...
}

FIGURE 7.2 The if-else Statement (Form 2)


Consider a store that offers a weekend discount of 10% for purchases over Rs 1000, and 5% otherwise.
The code that computes the amount payable can be represented in this manner:
if (total > 1000) total previously declared as float
total = total * 0.90; Or total *= 0.90;
else
total = total * 0.95; Or total *= 0.95;
printf(“The total amount payable is Rs %.2f\n”, total);
Because of proper indentation, it doesn’t take any effort to know that the printf statement is not
affected by the else clause and is executed unconditionally.

7.6 leap_year_check.c: PROGRAM TO CHECK LEAP YEAR


Let’s now use both forms of the if statement in our next program (Program 7.2). This program
subjects a user-input integer to a leap year check. A leap year is divisible by 4, so year % 4 is 0 for
a leap year. This program ignores the special check made for years that signify a change of century
(like 1800, 1900, etc.) but it indicates when the next leap year will occur.
Control Structures—Decision Making 213

/* leap_year_check.c: Checks for leap year using the if-else structure.


Doesn’t make the check for century. */
#include <stdio.h>
int main(void)
{
short year, years_left;
printf(“Enter year for leap year check: “);
scanf(“%hd”, &year);
if (year < 0) {
printf(“Invalid year\n”);
return 1;
}
if (year % 4 == 0) /* No parentheses required */
printf(“Year %hd is a leap year.\n”
“Next leap year is after 4 years.\n”, year);
else {
years_left = 4 - year % 4; /* No parentheses required */
printf(“Year %hd is not a leap year.\n”
“Next leap year is %hd.\n”, year, year + years_left);
}
return 0;
}

PROGRAM 7.2: leap_year_check.c


Enter year for leap year check: 2009 First invocation
Year 2009 is not a leap year.
Next leap year is 2012.

Enter year for leap year check: 2012 Second invocation


Year 2012 is a leap year.
Next leap year is after 4 years.

Enter year for leap year check: 1900 Third invocation


Year 1900 is a leap year. This is incorrect
Next leap year is after 4 years.

PROGRAM OUTPUT: leap_year_check.c

We have not used parentheses in the expression year % 4 == 0 because the % has a higher precedence
than == (Table 7.1). The modulus operation is thus performed first. The else part contains the code
for handling a non-leap year. Parentheses are left out in the expression 4 - year % 4 also because
the % has a higher priority than -.
In the last two printf statements, the first argument actually comprises two concatenated strings.
C allows this concatenation (9.12.2), but note that the combined string is actually a single argument
even if the strings are located on two physical lines.
214 Computer Fundamentals & C Programming

Tip: Always look for potential errors right at the beginning of the program. It’s pointless proceeding
with program execution with erroneous data. Use the if statements to check for them and then
use return with specific values to prematurely terminate the program.

7.7 MULTI-WAY BRANCHING WITH if-else-if ...


Nothing prevents us from using a second if statement (in any form) inside another if statement.
When the second if is inducted in the “if ” section, we have a nested if structure (if-if-else).
When the same is done in the “else” section, we have a ladder (if-else-if) instead. Both nested
and ladder structures belong to the domain of multi-way decision making. The nested form is
discussed in Section 7.10. The ladder structure is discussed here (Fig. 7.3).

if (expression is true) if (expression is true) {


statement; statements;
else if (expression is true) ...
statement; }
... else if (expression is true) {
else statements;
statement; ...
}
...
else {
statements;
...
}

FIGURE 7.3 The Ladder if-else-if Statement (Form 3)


The test on the control expression is carried out sequentially from the top downwards, and
terminates as soon as it evaluates to true. The last else statement takes care of “the rest” and is
executed only when all of the previous tests fail. C imposes no restriction on the number of else-if
sections that can be used in this manner.
Let’s now use this construct to compute the tariff for the 4G Internet service offered by a mobile
operator. The tariff is Rs 255 for up to 1 GB, Rs 455 for up to 2 GB, Rs 755 for up to 4 GB and Rs 995
thereafter (simplified from live data). This logic is easily implemented using the if-else-if form:
if (usage <= 1)
tariff = 255;
else if (usage <= 2)
tariff = 455;
else if (usage <= 4)
tariff = 755;
else “The rest”
tariff = 995;
This chained construct uses three different relational expressions that enable the variable tariff
to have one of four possible values. When using constructs that implement multi-way branching,
Control Structures—Decision Making 215

you must ensure that the expressions are mutually exclusive. This means that two expressions must
never evaluate to true in a single traversal of the structure.

/* irctc_refund.c: Computes refund amount on ticket cancellation. Negative


value for hours_left is valid. Maximum price of ticket = Rs 10,000 */
#include <stdio.h>
int main(void)
{
short hours_left, rate;
float ticket_price, refund_amount;
printf(“Enter price of ticket: “);
scanf(“%f”, &ticket_price);
printf(“Number of hours before train departure: “);
scanf(“%hd”, &hours_left);
if (ticket_price <= 0) {
printf(“Price can’t be negative\n”);
return 1;
}
else if (ticket_price > 10000) {
printf(“Price can’t exceed Rs 10,000.\n”);
return 1;
}
else if (hours_left > 48)
rate = 0;
else if (hours_left > 6)
rate = 25;
else if (hours_left > -2) /* 2 hours after departure */
rate = 50;
else
rate = 100; /* No refund */
refund_amount = ticket_price * (100 - rate) / 100;
printf(“Refund amount = %.2f\n”, refund_amount);
return 0;
}

PROGRAM 7.3: irctc_refund.c


Enter price of ticket: 11000
Number of hours before train departure: 45
Price can’t exceed Rs 10,000.

Enter price of ticket: 1000


Number of hours before train departure: 4
Refund amount = 500.00

Enter price of ticket: 1000


Number of hours before train departure: -1
Refund amount = 500.00

PROGRAM OUTPUT: irctc_refund.c


218 Computer Fundamentals & C Programming

Note: The return 0; statement at the bottom of the program is never executed because the program
exits through the paths provided by the other return statements placed in the inner ladder.
This return statement placed at the bottom should be removed.

7.10 MULTI-WAY BRANCHING WITH NESTED if (if-if-else)


We have seen the induction of an if-else section in the else part of the main if statement.
When the same section is inducted in the main if part itself (Fig. 7.4), we have a nested if (if-if-else)
structure. Like with the ladder, this is not a separate feature of the language but is derived from
the if syntax.

if (expression is true)
if (expression is true)
if (expression is true)
statement;
...
else
statement;
else
statement;
else
statement;
FIGURE 7.4 The Nested if-if-else Statement (Form 4)

The figure shows the indentation you must adopt when using nested if structures. Without proper
indentation, it is easy to visually pair an if with the wrong else. The pairing scheme is quite simple:
The innermost if pairs with the innermost else, the immediate outer if pairs with the immediate
outer else, and so on until the outermost if pairs with the outermost else. The symmetry breaks
down when you drop an else for one of the ifs, but more of that soon.
Let’s look at a simple example that demonstrates the usefulness of this derived construct. Consider
the need to print the sum of three positive integers obtained from user input, but only after validation.
Here’s the code snippet that handles the logic:
if (a > 0)
if (b > 0)
if (c > 0)
/* Cleared the validity check */
printf(“Sum of three integers = %d\n”, a + b + c);
else
printf(“c is not a positive integer\n”);
else
printf(“b is not a positive integer\n”);
else
printf(“a is not a positive integer\n”);
Control Structures—Decision Making 219

When code is presented in this way, there should be no problem in pairing an if with its else.
The first three if statements represent the AND condition (a > 0 && b > 0 && c > 0), so the first
printf signifies the action to take when all three expressions evaluate to true. The other printf
statements are associated with the else clauses and they tell us what happens when each of the
variables is less than or equal to zero.
In some cases, we need to drop some of the else keywords, or even all of them. The latter is easy
to handle, but we have to handle the other situations with care. Before we do that, let’s have a look
at a program which contains a symmetric nested if structure.

7.11 right_angle_check.c: PROGRAM TO CHECK PYTHAGORAS’ THEOREM


Our knowledge of geometry tells us that the square of the hypotenuse of a right-angled triangle
is equal to the sum of the squares of the other two sides. This means that given three numbers a,
b and c, if a * a + b * b is equal to c * c, then a right-angled triangle can be formed with these
three sides, where the largest side represents the hypotenuse.
Program 7.5 runs an infinite while loop to accept three integers (a, b and c) from the keyboard.
It allows a user multiple chances to key in non-zero values, and then tries all possible combinations
of a, b and c to see if one of them fits the formula. It’s good to know how nested if constructs work
even though a better and more intuitive approach would be to use the if-else-if ladder.
The program first validates the integers for non-zero values; it terminates when all of them are zero.
After successful validation, control moves to the nested construct comprising four if statements.
The first if (the outermost one) allows only positive integers to pass through. If this test fails,
the matching else at the bottom uses printf to display a non-specific error message. Because this
entire construct runs in a loop, control then moves up to the beginning of while to accept the next
set of integers.
Once the three integers pass the second validation test, the program tries out three possible
combinations (a-b-c, a-c-b and b-c-a) that will not fit the theorem. In other words, if all three
relational expressions evaluate to true, then a right-angled triangle cannot be formed with any
combination of these integers. If one of the expressions fails, its corresponding else section uses
printf to tell us that a right-angled triangle can be formed, and it also tells us what the hypotenuse is.

7.12 PAIRING ISSUES WITH if-if-else NESTED CONSTRUCTS


We didn’t face any pairing problems in the previous program (Program 7.5) because the nested if
construct had an equal number of if and else clauses. It was easy to see which else paired with
which if. Sometimes, program logic may not need one or more else clauses. A small code fragment
having an else missing is shown in Figure 7.5 with both misleading and correct indentation.
The indentation of the else part in the form shown on the left is deceptive. It gives the impression
that the else is paired with the first if, which it is not. The form on the right correctly shows the
else paired with the inner if. Even though the compiler doesn’t look at indentation, we can’t
afford to ignore it.
220 Computer Fundamentals & C Programming

/* right_angle_check.c: Uses nested if statements. Doesn’t catch


exact cause of failure. Formula used: a*a + b*b = c*c */
#include <stdio.h>
int main(void)
{
short a, b, c;
while (1) {
printf(“Enter three integers a b c: “);
scanf(“%hd %hd %hd”, &a, &b, &c);
if (a == 0 && b == 0 && c == 0) {
printf(“All values zero. Quitting ...\n”);
return 1;
}
/* RAT represents right-angled triangle */
if (a > 0 && b > 0 && c > 0)
if (a * a + b * b != c * c) /* Whether RAT can’t be formed */
if (a * a + c * c != b * b) /* Ditto */
if (b * b + c * c != a * a) /* Ditto */
printf(“RAT not possible.\n”);
else
printf(“RAT with %hd as hypotenuse.\n”, a);
else
printf(“RAT with %hd as hypotenuse.\n”, b);
else
printf(“RAT with %hd as hypotenuse.\n”, c);
else
printf(“At least one input is invalid.\n”);
}
}

PROGRAM 7.5: right_angle_check.c


Enter three integers a b c: 5 0 9
At least one input is invalid.
Enter three integers a b c: 3 5 4
RAT with 5 as hypotenuse.
Enter three integers a b c: 5 2 6
RAT not possible.
Enter three integers a b c: 6 10 8
RAT with 10 as hypotenuse.
Enter three integers a b c: 0 0 0
All values zero. Quitting ...

PROGRAM OUTPUT: right_angle_check.c


Control Structures—Decision Making 221

Misleading Indentation Correct Indentation


if (a > 0) if (a > 0)
if (b > 0) if (b > 0)
valid_int = ‘y’; valid_int = ‘y’;
else else
valid_int = ‘n’; valid_int = ‘n’;

FIGURE 7.5 Code with a Missing else


But what if you actually wanted an else part for the first if and not for the second? There are
two solutions to this problem. One is to use curly braces to eliminate ambiguity. The other is to
use a dummy else containing a solitary semicolon. The ; placed by itself on a line signifies a null
statement—one that does nothing. The two solutions are placed side-by-side in Figure 7.6 for you
to choose the one you prefer. The curly brace solution is the one that is preferred by most.

Null Command Solution Curly Brace Solution


if (a > 0) if (a > 0) {
if (b > 0) if (b > 0)
valid_int = ‘y’; valid_int = ‘y’;
else }
; else
else printf(“a is <= 0\n”);
printf(“a is <= 0\n”);

FIGURE 7.6 Two Solutions for Missing else

7.13 leap_year_check2.c: PROGRAM USING THE if-if-else STRUCTURE


Let’s conclude our discussions on the if statement by improving a previous leap year checking
program. The revised version (Program 7.6) includes the special check for the “century” years
(like 1900, 2000, etc.). We use a symmetric nested if-if-else structure where there is no else
missing. The use of the variable is_leap_year should be an eye-opener because of the remarkable
way it has been used.
You are aware that all years that signify a change of century are not leap years even though they
are all divisible by 4. Years like 1900 and 2000 have to be divisible by 400, which means that 2000
is a leap year but 1900 is not. To identify a leap year, we must follow this course of action:
1. Check whether the number is divisible by 4. If it is not, the number is not a leap year and the
program terminates.
2. If the previous check succeeds, divide the number by 100 to determine whether the year
represents a change of century. If it is not, then the number represents a leap year and the
program terminates.
3. If we have come here, it means that we are dealing with a century year. Now check whether
the number is divisible by 400. If it is, the number is a leap year and the program terminates.
4. If we have come here, the number doesn’t represent a leap year.
224 Computer Fundamentals & C Programming

The combination of the three expressions itself constitutes a larger expression—the conditional
expression. This expression has the value exp2 if exp1 evaluates to true, and exp3 otherwise. Even if
this construct has been discussed in Chapter 6 as a special form of expression, it is also important
for decision making. In fact, this operator easily replaces those if-else statements that merely set a
variable. Consider the following if statement which is shown side-by-side with the ternary version:
if-else Version Equivalent Conditional Expression
if (total > 1000) rate = total > 1000 ? 0.90 : 0.95;
rate = 0.90;
else
rate = 0.95;

Using a conditional expression, the leap year problem becomes even shorter. Simply set the variable
is_leap_year to ‘y’ or ‘n’ depending on the value of a logical expression. Use parentheses if they
help to provide clarity:
char is_leap_year;
is_leap_year = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
? ‘y’ : ‘n’;
Now, printf and scanf are also expressions because both return a value, so can we use printf in
this way?
count = inta < 0 ? printf(“Invalid value\n”) : printf(“Valid integer\n”);

Yes, this is a valid statement. In the process of evaluation of printf, the side effect (printing) also
shows up. The variable count stores the return value of printf, i.e., the number of characters printed.
Note that the ; at the end is the terminator of the assignment statement. The first printf doesn’t
have a terminator, so why should the second printf have one?

7.15 THE switch STATEMENT


We use the equality test so often that C has a special construct to handle it. It’s the switch statement
which implements multi-way branching with a compact and structured construct. If you need to
match 10 integer values for making 10 different decisions, use switch whose syntax is shown in
Figure 7.7.

switch (exp) {
case value1 : statements1;
break;
case value2 : statements2;
break;
...
default : statements;
}

FIGURE 7.7 Syntax of switch Statement


Control Structures—Decision Making 225

switch first evaluates exp which must be an integer or character variable or constant. It next tries to
match exp with value1. If the match succeeds, switch executes one or more statements represented
by statements1. If the match fails, switch attempts to match exp with value2 and so on until control
moves to the keyword default (if present). This option is thus invoked when all previous matching
operations fail. For this purpose, switch is assisted by three keywords—case, break and default.
The entire set of options and their associated action are enclosed in curly braces.
Every case represents an option that specifies the statements to be executed in case matching is
successful. In most cases, a case is followed by break. When it is encountered, further matching is
halted and control moves past the end of switch to the statement following the }. In the absence of
break, however, control “falls through” to the next case option for the next break, or past the end
of switch if it doesn’t find one. Program 7.9 clearly shows us why switch was designed to behave
in this unusual manner.
Here’s a simple code fragment that shows the working of switch. It validates a user-input integer
for the values 1 and 2:
printf(“Enter a 1 or 2: “);
scanf(“%d”, &response);
switch (response) {
case 1: printf(“You entered 1\n”);
break;
case 2: printf(“You entered 2\n”);
break;
default: printf(“Invalid option\n”); No break required ...
} ... will break anyway
The default keyword (if present) doesn’t need a break since control will anyway break out of the
construct at the point where it could have occurred. However, switch operates with the following
restrictions:
exp can be any expression as long as it evaluates to an integer or character constant like
1, 2 or ‘y’.
The labels value1, value2, etc. can only be integer or character constants or constant expressions
(like 3 + 5). Floating point values and variables are not permitted here.
The label is always followed by a colon, and the statements associated with it must be
terminated by semicolons.
The default label is optional, but if present, is usually placed as the last option (not
mandatory though).
Two or more labels can have one break statement. This feature gives switch the power of the
logical OR operator.
It is permissible to have an empty case (one without any statement).
Can a relational expression be used as exp? Sure it can, but the evaluation would yield only one
of two values. You can use switch to match the labels 0 and 1, but then if is ideally suited for this
task. Program 7.9 uses a relational expression for exp.
8 Control Structures—Loops

Chapter 8, Sections 8.1-8.3, and 8.5-8.6.


WHAT TO LEARN

Principles of entry and exit in loops.


Concept of the key variable used in a control expression and loop body.
Working of the while construct as an entry-controlled loop.
Working of the do-while construct as an exit-controlled loop.
Significance of three expressions for controlling iterations in a for loop.
Nesting of all loops.
Interrupting loop processing with break and continue.

8.1 LOOPING BASICS


Many activities that we perform daily are repetitive in nature. Repetition makes us breathe, moves
automobiles and drives production lines. In most cases, the repetition framework also includes the
mechanism to halt itself. Repetition also extends to areas that computer programs handle with ease.
Consider the following tasks that involve repetition:
Computation of average—requires repeated addition.
Computation of the power of a number—requires repeated multiplication.
Initialization of an array—requires repeated assignment.
Decimal-to-binary conversion—requires repeated division.
Drawing a line—requires repeated printing of a character.
In addition to decision making, a language must be able to repeatedly execute a a set of statements.
Constructs that do that are known as loops, and C offers three of them—while, do-while and
for. Before we get down to the specifics, we need to know in generic terms how a loop works.
Figure 8.1 shows the working of a generic loop which here prints the entire English alphabet in
uppercase.
Control Structures—Loops 237

1. Initialize key variable (x) outside loop.


(say, x = 65)
2. Test control expression at loop beginning.
(Is x <= 91?)
3. If answer to 2 is yes, perform steps 4 to 6.
Beginning of Loop
4. Execute loop body to print one letter.
(printf(“%c “, x))
5. Assign the next higher value to key variable.
(x = x + 1)
6. Go back to 2 to re-test control expression.
End of loop
7. If answer to 2 is no (i.e. x > 91), continue execution after loop
(say, printf(“\nJob over\n”)).

FIGURE 8.1 How a Loop Works

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Job over

Output of Pseudo-Code

Before a loop begins, a key variable is initialized (1). This variable is used to evaluate a control
expression (2). If the evaluation is true (3), the loop body is executed (4 to 6), otherwise control moves
to the next statement after the loop (6). The key variable is then changed in the loop body (5) before
control moves back to the beginning of the loop (2). The control expression is now re-checked (2)
before the next iteration (traversal or repeat) can begin. If the loop is designed to run a finite
number of times, the control expression will eventually turn false and cause the loop to terminate.
Even though all of the three loops offered by C broadly conform to the above scheme, there are
minor differences between them. First, the initialization may be done in the loop construct itself
(for loop) instead of being done outside. Second, the control expression may be evaluated at
the end (do-while loop) instead of at the beginning. Finally, a control expression can’t prevent
a do-while loop from performing at least one iteration even though it can prevent the other loops
from running at all.
A loop iteration can either be suspended (to start a new one) or terminated altogether without
re-testing the control expression. This is achieved with the continue and break keywords that can
be invoked anywhere in the loop body. You have already used this feature in one program of the
previous chapter, so you’ll find it a convenient alternative to the traditional method of using the
control expression to determine loop continuity.
238 Computer Fundamentals & C Programming

A loop is generally designed to execute a finite number of times, but many applications need
a loop to run all the time. Such loops are known as infinite loops. We have seen one of them in the
previous chapter (while (1)). Many Internet services use infinite loops to check whether a mail
has been received or a user has keyed in text in a messaging application. However, even infinite
loops can be terminated by other means.

8.2 THE while LOOP


You have seen the while loop at work in some of the previous chapters. The syntax, featuring both
single and compound statements in the loop body, is shown in Figure 8.2. Don’t forget to enclose
the control expression in parentheses.

while (expression is true) while (expression is true) {


statement; statement1;
statement2;
...
}

FIGURE 8.2 The while Statement

The while loop is virtually identical to the generic loop that was depicted in Figure 8.1. An expression
containing a key variable is evaluated to true or false before loop iteration. If false, the loop is not
entered at all, otherwise the body of the loop is executed. After execution, control reverts to the top to
test expression that will determine whether the next iteration can begin. Since the key variable changes
with every iteration, eventually its value causes expression to turn false and terminate the loop.

8.2.1 while_intro.c: An Introductory Program


Let’s examine a small program (Program 8.1) that computes the sum of the first 10 integers and
prints both a progressive and final sum. The key variable here is i, which is used three times in
a while loop. Since this loop is finite, i will eventually exceed 10. The control expression will then
turn false and prevent loop re-entry. The progressive sum is printed inside the loop and the final
sum outside.
The while loop is an entry-controlled loop, which means that loop entry is not guaranteed. If the
control expression is false to begin with, then the loop is not entered at all. This is also true of
the for loop, but not the do-while loop which is an exit-controlled loop. The control expression in
a do-while loop is tested at the end of the loop, which means that initial loop entry is guaranteed
but not its subsequent iterations.

8.2.2 The Control Expression


The control expression is the nerve center of any loop. C lets you use any expression (relational,
logical or constant) as long as it evaluates to an integer value. Any control expression used with
if in Chapter 7 will work in identical manner with all loops. Here are some examples of usage of
these expressions:
Control Structures—Loops 239

/* while_intro.c: A simple while loop that prints the sum of the


first 10 integers. Also prints progressive sum. */
#include <stdio.h>
#define NO_OF_INTEGERS 10
int main(void)
{
short i = 1; /* Key variable initialized */
short sum = 0;
printf(“Progressive sum shown below:\n”);

while (i <= NO_OF_INTEGERS) { /* Key variable tested */


sum += i;
i++; /* Key variable updated */
printf(“%hd “, sum);
}
/* Loop has terminated */
printf(“\nSum of first %d integers = %hd\n”, NO_OF_INTEGERS, sum);
return 0;
}

PROGRAM 8.1: while_intro.c


Progressive sum shown below:
1 3 6 10 15 21 28 36 45 55
Sum of first 10 integers = 55

PROGRAM OUTPUT: while_intro.c

while (reply == ‘y’) Relational expression


while (++num <= power) As above, but with a difference
while (base > 0 && power >= 0) Logical expression
while (quot) Expression is a variable
while (1) Expression is a constant
while (printf(“Enter an integer: “)) Expression is a function
The second expression is an eye-opener; it contains the updating of the key variable (num) in the
control expression itself. The statement while (quot) is the same as while (quot > 0). By the same
token, while (1) is always true. The last expression using printf is also true because it evaluates
to the number of characters printed.

8.2.3 Updating the Key Variable in the Control Expression


As discussed before, most loop applications are based on the initialize-test expression-update
key variable model:
Initialize the key variable.
Test it in the control expression.
Update the key variable in the loop body.
240 Computer Fundamentals & C Programming

However, we can sometimes update the key variable in the control expression itself and get rid of one
statement in the loop body. The following code related to the program while_intro.c will also work:
short i = 0, sum = 0; i initialized to 0 not 1
while (++i <= 10) { ++i instead of i
sum += i;
printf(“%hd “, sum);
}
printf(“\nSum of first 10 integers = %hd\n”, sum); Prints 55
The updating of the key variable i has now been moved to the control expression, but this movement
needs the initial value of i to be changed as well.
Note: When you change the key variable in the control expression to one having prefix or postfix
operators, you also need to change either the relational operator (say, > to >=) or the initial value of
the key variable.

8.3 THREE PROGRAMS USING while


Before we continue exploring this loop in C, let’s examine three simple programs that use simple
control expressions. All of these programs are revised in subsequent chapters to use arrays and
functions. Two of the later versions also use the recursive technique in contrast to the iterative
approach of loops that is pursued here.
8.3.1 factorial.c: Determining the Factorial of a Number
The factorial of a positive integer n (denoted by !n) is the product of all positive integers less than
or equal to n. Thus, !4 = 4 ¥ 3 ¥ 2 ¥ 1 = 24. Program 8.2 uses a while loop to compute the factorial
of an integer supplied by the user. Section 11.13.1 shows an alternative way of solving the same
problem using a function.
/* factorial.c: Program to determine factorial of a number
without using a function. */
#include <stdio.h>
int main(void)
{
short num1, num2;
unsigned int factorial = 1; /* unsigned doubles the maximum value */
printf(“Factorial of which number? “);
scanf(“%hd”, &num1);
num2 = num1; /* Saving num1 before it changes */
while (num1 >= 1) {
factorial *= num1;
num1--;
}
printf(“Factorial of %hd = %d\n”, num2, factorial);
return 0;
}

PROGRAM 8.2: factorial.c


Control Structures—Loops 241

Factorial of which number? 4


Factorial of 4 = 24
Factorial of which number? 6
Factorial of 6 = 720
Factorial of which number? 1
Factorial of 1 = 1

PROGRAM OUTPUT: factorial.c


8.3.2 extract_digits.c: Program to Reverse Digits of an Integer
Program 8.3 performs the dual task of reversing the digits of an integer and printing their sum.
Using 10 as the divisor, each digit is extracted from the right using the / and % operators. The program
has the demerit of not saving the digits, so you can’t perform any other task with them once printing
is complete.
/* extract_digits.c: Reverses the digits of an integer. Prints and sums
the digits using the % and / operators. */
#include <stdio.h>
int main(void)
{
unsigned int number;
short last_digit, sum = 0;

printf(“Key in an integer: “);


scanf(“%d”, &number);

while (number != 0) {
last_digit = number % 10; /* Extracts last digit */
number = number / 10; /* Removes last digit */
sum += last_digit;
printf(“%hd “, last_digit);
}
printf(“\nSum of digits: %hd\n”, sum);
return 0;
}

PROGRAM 8.3: extract_digits.c


Key in an integer: 13569
9 6 5 3 1
Sum of digits: 24

PROGRAM OUTPUT: extract_digits.c


In every iteration of the while loop, the / operation removes the last digit and the % operation saves
this digit. This is how the values of the variables last_digit and number change with every loop
iteration:
242 Computer Fundamentals & C Programming

Iteration 1 Iteration 2 Iteration 3 Iteration 4 Iteration 5


last_digit 9 6 5 3 1
number 1356 135 13 1 0

The program is inflexible; we can’t use this technique to print the digits in the sequence they
occur in the number. We need to save every digit, not with five variables, but with an array of five
elements. We’ll revisit the program in Section 10.7.1.

8.3.3 fibonacci_ite.c: Printing and Summing the Fibonacci Numbers


Every student of computer science would have encountered the Fibonacci sequence of numbers
at some point in their learning curve. In this sequence, which starts with the values 0 and 1, each
subsequent term is the sum of the previous two. This relationship can be seen in the first 12 terms
of this sequence:
0 1 1 2 3 5 8 13 21 34 55 89

Here, 55 is the sum of its two predecessors, 34 and 21, while 21 is the sum of 13 and 8. Program
8.4 prints and sums n terms of the sequence where n is provided by the user. The program employs
a while loop that runs n times. In each iteration, the sum of the variables prev1 and prev2 are saved
in sum and printed. Note that the first two terms are generated from the logic which has not treated
them in an exceptional manner. This has been made possible by careful selection of the initialized
values of four variables.
/* fibonacci_ite.c: Uses the iterative technique to generate terms of
the Fibonacci series and compute the sum of terms. */
#include <stdio.h>
int main(void)
{
short num;
unsigned long prev1 = 0, prev2 = 0, sum = 1, sum_terms = 0;
short i = 0;
printf(“Enter last term of series: “);
scanf(“%hd”,&num);
while (i++ < num) {
printf(“%ld “, sum); /* Prints each term */
sum_terms += sum; /* Sums all terms */
prev1 = prev2;
prev2 = sum;
sum = prev1 + prev2; /* Sums previous two terms */
}
printf(“\nSum of first %hd terms = %ld\n”, num, sum_terms);
return 0;
}

PROGRAM 8.4: fibonacci_ite.c


Control Structures—Loops 243

Enter last term of series: 15


1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
Sum of first 15 terms = 1596

PROGRAM OUTPUT: fibonacci_ite.c

The Fibonacci sequence can also be generated by using a recursive function, i.e., a function that
calls itself repeatedly. Section 11.14.3 examines this function and its demerits compared to the
iterative approach used here.
8.4 LOADING THE CONTROL EXPRESSION
Repetition creates opportunities for using functions as control expressions. For instance, the getchar
function, a member of the I/O family of functions, fetches a character from the keyboard and
returns its ASCII value. The putchar function uses this value to display the character. Consider
the following code snippet:
int c;
c = getchar(); Gets the first character
while (c != EOF) { EOF is end-of-file
putchar(c); Displays the character
c = getchar(); Fetches the next character
}

This appears to be a simple way of retrieving a string of text from keyboard input. But because
getchar returns the ASCII value of the fetched character, you can move the getchar statement
itself to the control expression:
while ((c = getchar()) != EOF)
putchar(c);
This works perfectly and looks clean as well because a single getchar is used. The != has a higher
precedence than the =, so parentheses must be provided around the assignment (c = getchar()). This
ensures that the return value of getchar is assigned to c before c is compared to EOF (end-of-file).
Many functions return a value. scanf returns the number of items successfully read and printf
returns the number of characters written, so these functions can also be used as control expressions:
while (scanf(“%d”, &num) == 1)
while (printf(“Enter the amount: “))
Both getchar and putchar are discussed in Chapter 9 which examines the major I/O functions.
The scanf and printf functions are also examined in the same chapter.

8.4.1 Merging Entire Loop Body with the Control Expression


A previous example merged both calls to getchar to a single call in the control expression. But putchar
also returns a value (that of the character written), so why not move it too to the control expression?
Yes, we can do that as well:
244 Computer Fundamentals & C Programming

while ((c = getchar()) != EOF && putchar(c))


; Null statement
The value of the expression putchar(c) is c. This value is true for all ASCII characters except the
NUL character, so the putchar expression is always true. This compound expression will turn false
only when the input to getchar is exhausted. Since this loop has no body, don’t forget to follow the
while statement with a semicolon, preferably on a separate line.

Tip: Don’t merge too many statements with the control expression if that destroys clarity. Program
clarity is more important than compactness. In the preceding case, you should stop after moving
getchar to the control expression. The putchar statement is better left in the loop body.

8.4.2 When You Actually Need a Null Body


There are situations when you actually need to have a null body. When scanf is used with the
%c format specifier in a loop, whitespace characters often get trapped in the buffer. Subsequent
invocations of scanf get these trapped characters rather than fresh user input. So, before you call
scanf again, call getchar repeatedly to empty the buffer:
scanf(“%c”, &reply); \n generated by [Enter] remains in buffer
while (getchar() != ‘\n’) \n removed from buffer
; No further action needed
Here, getchar continues reading from the buffer until it encounters the newline. This ensures that
the next scanf call operates with an empty buffer. A null body is mandatory because the control
expression itself has done the job of clearing the buffer.
Caution: When using while (or any loop) without a formal body, remember to place a semicolon
immediately below it to indicate that the loop runs a null command. If you fail to provide the ;,
the statement following while will be considered as the body of the loop, which obviously is not intended.

8.5 NESTED while LOOPS


Just as an if statement can contain another if statement, nothing prevents us from using a second
while inside an outer while construct. Figure 8.3 presents two views of the structure of a nested
while loop. The view on the right highlights the way it is normally used. It shows the locations of
initialization and updating of key variables of both loops.
The nested loop starts with the initialization of key variable1, followed by evaluation of expression1.
If the result is true, the outer loop is entered. Before entry into the inner loop, key variable2 is
initialized. If and after expression2 evaluates to true, the inner loop is entered. When this loop
terminates, key variable1 of the outer loop is updated before control moves to the top of this loop
for re-evaluation of expression1.
Thus, each iteration of the outer loop leads to multiple iterations of the inner loop. The three
programs that follow make use of this one-to-many relationship that exists between the inner and
outer while loops.
Control Structures—Loops 245

Syntax Form Usage Form


while (expression1) { initialization1
... while (expression1) {
while (expression2) { ...
... initialization2
} while (expression2) {
} ...
Update key variable2
}
Update key variable1
}

FIGURE 8.3 Structure of a Nested while Loop

8.5.1 nested_while.c: Printing a Multiplication Table


Consider printing a table of x rows and y columns. This is done by printing all y columns of one
row before taking up the next row. The task is completed with the printing of the yth column of
the xth row. A nested while construct is thus the perfect choice for handling two-dimensional data
like tables and arrays as the following program (Program 8.5) shows.
/* nested_while.c: Uses nested while loop to print multiplication table
for positive integers up to 5. Maximum size of multiplier = 12 */
#define ROWS 5
#define COLUMNS 12
#include <stdio.h>
int main(void)
{
int x = 0, y; /* Key variable x initialized here ... */
while (x++ < ROWS) { /* ... and updated in control expression */
y = 0; /* Key variable y initialized here ... */
while (y++ < COLUMNS) /* ... and updated in control expression */
printf(“ %3d”, x * y);
printf(“\n”);
}
return 0;
}

PROGRAM 8.5: nested_while.c


1 2 3 4 5 6 7 8 9 10 11 12
2 4 6 8 10 12 14 16 18 20 22 24
3 6 9 12 15 18 21 24 27 30 33 36
4 8 12 16 20 24 28 32 36 40 44 48
5 10 15 20 25 30 35 40 45 50 55 60

PROGRAM OUTPUT: nested_while.c


246 Computer Fundamentals & C Programming

8.5.2 half_pyramid.c: Printing a Half-Pyramid with Digits


You need to use nested loops to print predictable two-dimensional patterns like pyramids and half-
pyramids. Consider the following pattern that uses digit-characters where the digit used is also the
sequence number of the row:
1
2 2
3 3 3
4 4 4 4
Even though the for loop is an automatic choice for tasks such as the one above, the next program
(Program 8.6) uses two while loops to print this half-pyramid. The number of rows to be printed
is taken as user input. Observe that one key variable (col) is updated in the control expression but
the other (row) is not. That is because row is used in both control expressions.

/* half_pyramid.c: Uses a nested while structure to print a half-pyramid. */


#include <stdio.h>
int main(void)
{
short row = 1, col, rows_max;
printf(“Number of rows? “);
scanf(“%hd”, &rows_max);
while (row <= rows_max) {
col = 1; /* Key variable col initialized here ... */
while (col++ <= row) /* ... and updated in control expression */
printf(“%d “, row); /* Prints row number in each row */
row++;
printf(“\n”); /* Moves to next row */
}
return 0;
}

PROGRAM 8.6: half_pyramid.c


Number of rows? 5
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5

PROGRAM OUTPUT: half_pyramid.c

Since there is no limit on the depth of nesting (i.e., the number of inner loops possible), you can
handle multi-dimensional data quite easily.
Control Structures—Loops 247

Takeaway: In a nested while structure there is a one-to-many relationship between the outer
and inner loop. For every iteration of the outer loop, the inner loop must complete its set of
iterations before the next iteration of the outer loop can begin.

8.5.3 power.c: Computing Power of a Number


Program 8.7 uses an outer loop to take two integers (x and y) as user input. It then uses an inner
loop to compute the value of x raised to the power y. The program handles only positive integers but
quits when the user keys in a zero (for the first number) or a negative integer (for both numbers).

/* power.c: Computes power of multiple sets of numbers using a nested


while loop. Repeatedly multiplies a number by itself. */
#include <stdio.h>
int main(void)
{
short num, base = 1, power = 1;
unsigned long total;
while (base > 0 && power >= 0) {
printf(“Enter base and power (0 0 to exit): “);
scanf(“%hd%hd”, &base, &power);
if (base <= 0 || power < 0) { /* Invalid Input */
printf(“Invalid Input. Quitting ...\n”);
return 1;
}
num = 0; total = 1; /* Initialization before inner loop */
while (++num <= power)
total *= base; /* Multiply base by itself */
printf(“%d to the power %d = %lu\n”, base, power, total);
}
return 0;
}

PROGRAM 8.7: power.c


Enter base and power (0 0 to exit): 2 0
2 to the power 0 = 1
Enter base and power (0 0 to exit): 2 10
2 to the power 10 = 1024
Enter base and power (0 0 to exit): 0 0
Invalid Input. Quitting ...

PROGRAM OUTPUT: power.c


248 Computer Fundamentals & C Programming

The outer while loop repeatedly prompts for two integers. After performing the necessary validation,
the program passes on valid numbers to the inner loop. For each iteration of this loop, total is
assigned the values base, base * base, base * base * base, and so forth until the key variable num
equals power that is set by user input.
Note: The maths library supports the pow function which does the same job as this program.
Chapter 12 features a program that uses this function. For a program containing pow, the compilation
process is different: the linker must be explicitly invoked to include the code of pow in the executable.

8.6 USING while WITH break AND continue


The while loops seen so far used the control expression to determine whether it should iterate
or terminate. However, some situations demand immediate suspension of the current iteration
to either break out of the loop or restart a new iteration. C supports two keywords—break and
continue—that can perform these two tasks (Fig. 8.4).
When the program sees break, control breaks out of the loop to resume execution from the statement
immediately below the end of the loop. On the other hand, continue doesn’t terminate a loop but
suspends loop execution to resume the next iteration. Both situations usually occur when a variable or
expression used in the loop acquires a value that makes further execution of statements undesirable.

while (expression is true) {

statements;
break;

statements;
continue;

statements;
}

statements;

FIGURE 8.4 How continue and break Behave in a while Loop


The next program (Program 8.8) uses an infinite while loop to enable repeated entry of three positive
numbers. It uses continue to ask for a new set of numbers in case at least one of them is found to be
negative. If the numbers are all positive, then the break statement terminates the loop. The printf
statement below the closing brace of while then prints the sum of the numbers. The program also
terminates when zero is input for all three numbers.
Control Structures—Loops 249

/* break_continue.c: Uses break and continue in a loop. */


#include <stdio.h>
int main(void)
{
short a, b, c;
while (1) {
printf(“Enter three integers a b c: “);
scanf(“%hd %hd %hd”, &a, &b, &c);

if (a == 0 && b == 0 && c == 0) {
printf(“All values zero. Quitting ...\n”);
return 1;
}
else if (a < 0 || b < 0 || c < 0) {
printf(“Negative integer not allowed\n”);
continue; /* Goes to while (1) */
}
else
break; /* Goes to next printf statement */
}
printf(“Sum of %d %d %d: %d\n”, a, b, c, a + b + c);
return 0;
}

PROGRAM 8.8: break_continue.c


Enter three integers a b c: 3 4 -5
Negative integer not allowed
Enter three integers a b c: 3 4 5
Sum of 3 4 5: 12
Enter three integers a b c: 0 0 0
All values zero. Quitting ...

PROGRAM OUTPUT: break_continue.c


Structured programming theorists disapprove of the use of break and continue. They feel that
loops should provide a single point of exit (where the control expression is tested). But this
arrangement comes at a price; a number of variables need to be set and tested at various points in
the loop. After you have used break and continue, you may not be willing to pay that price.

8.7 prime_number_check.c: MORE OF break AND continue


We end our discussions on the while loop with Program 8.9, which checks whether a number
is prime or not. A prime number is one that is not divisible by any number other than itself
and 1. The program accepts multiple numbers from the keyboard and terminates when zero is
input. The exercise is carried out in a nested while loop structure that uses break and continue.
The program is grouped into four sections.
Lesson 3: For Loop

Control Structures—Loops 253

Enter a decimal integer: 35


Chapter
1 1 08,0 Sections
0 1 8.10-8.15 Binary of 35 is 100011
Number of iterations = 6
Enter a decimal integer: 128
0 0 0 0 0 0 0 1
Number of iterations = 8

PROGRAM OUTPUT: decimal2binary.c


The number obtained from user input is subjected to repeated division and modulo operation in
a do-while loop. The loop terminates when quot, which progressively decreases with each iteration,
eventually drops to zero. Because the generated bits are not saved, the program can’t reverse them.
To correctly represent the binary equivalent of the number, we need to use an array to store the bits
and then read the array backwards. We’ll improve this program in Section 8.12.

8.10 THE for LOOP


Like while and do-while, the for loop also uses the key variable/control expression paradigm to
determine loop entry and continuity. It is a compact construct that gathers three expressions at
one place (Fig. 8.6). Any while loop can be replaced with a for loop, and for many, the latter is
the preferred loop.

for (exp1; exp2; exp3) for (exp1; exp2; exp3) {


statement; statement1;
statement2;
...
}

FIGURE 8.6 The for Statement

The while loop works on the principle of initializing a key variable before the loop, testing it in
the control expression and updating the key variable in the body. The three expressions in for do
the same work but at one place. The initialization is done by exp1, the key variable check is done
by exp2, and updating of the key variable is done by exp3. These expressions, which are delimited
by semicolons, determine whether a loop will run, and if so, how many times.
The left side of Figure 8.7 shows the use of a for loop to print the ASCII values of the uppercase
letters. The right side shows the equivalent code using while. All three expressions in for are not
evaluated in every loop iteration, so let’s understand the sequence of operations used by for in
this program:
1. The first expression (chr = 65 and exp1 in syntax) initializes the key variable (chr).
2. The second expression (chr < 91 and exp2), which is the control expression for this loop, is
evaluated. If the evaluation is true, the loop is entered.
254 Computer Fundamentals & C Programming

#include <stdio.h> #include <stdio.h>


int main(void) int main(void)
{ {
int chr; int chr = 65;
for (chr = 65; chr < 91; chr++) while (chr < 91) {
printf(“%c=%d “, chr, chr); printf(“%c=%d “, chr, chr);
return 0; chr++;
} }
return 0;
}

PROGRAM OUTPUT:
A=65 B=66 C=67 D=68 E=69 F=70 G=71 H=72 I=73 J=74 K=75 L=76 M=77 N=78 O=79 P=80
Q=81 R=82 S=83 T=84 U=85 V=86 W=87 X=88 Y=89 Z=90

FIGURE 8.7 Difference in Form Between for (left) and while (right)
3. If the result of evaluation in Step 2 is true, the printf statement is executed.
4. After an iteration has been completed, control moves to the third expression (chr++ and exp3)
where the key variable is incremented.
5. Control now goes back to Step 2 where the control expression is re-tested. The loop starts the
next iteration if chr is still less than 91.
6. chr will eventually have the value 91. The control expression will then turn false and prevent
loop re-entry. The return statement terminates the program.
Like while, for is an entry-controlled loop because exp1 and exp2 jointly determine whether
the loop will be entered at all. This loop is special because of the flexibility of expression usage.
Any of these three expressions can comprise comma-separated multiple expressions, or it can be
dropped altogether. Using this feature, you can dismantle the set of three expressions to provide
a “while”-like look to for:
int chr = 65; exp1
for (; chr < 91;) { exp2
printf(“%c=%d “, chr, chr);
chr++; exp3
}
Here, exp1 and exp3 have been moved out, leaving their slots with null expressions. The semicolons
are mandatory even if the expressions are absent. Like in while, some statements of the loop body
can also be moved to the control expression.

Takeaway: In the first iteration of a for loop, the sequence is exp1 followed by exp2.
In subsequent iterations, it is exp3 followed by exp2. exp1 is evaluated only once—before the
loop is entered.
Control Structures—Loops 255

8.10.1 ascii_letters.c: A Portable ASCII Code Generator


Program 8.11 generates the machine values of the lowercase letters. It prints on each line the
values of nine letters in the form letter=value. The program is fully portable because, unlike the
previous program which works with specific ASCII values, this program works with the character
representation of the letters. As a consequence, the program will run without modification on both
ASCII and EBCDIC systems.

/* ascii_letters.c: A portable version of the ASCII list generator.


Runs without modification on EBCDIC machines. */
#include <stdio.h>
int main(void)
{
short chr, count = 0;
short diff = ‘a’ - ‘A’; /* Will be different in EBCDIC and ASCII */
for (chr = ‘A’; chr <= ‘Z’; chr++) {
printf(“%c = %3hd “, chr + diff, chr + diff);
if (++count == 9) { /* Nine entries in one line only */
printf(“\n”);
count = 0;
}
}
return 0;
}
PROGRAM 8.11: ascii_letters.c
a = 97 b = 98 c = 99 d = 100 e = 101 f = 102 g = 103 h = 104 i = 105
j = 106 k = 107 l = 108 m = 109 n = 110 o = 111 p = 112 q = 113 r = 114
s = 115 t = 116 u = 117 v = 118 w = 119 x = 120 y = 121 z = 122

PROGRAM OUTPUT: ascii_letters.c

The machine values of A and a in ASCII are 65 and 97, respectively. Machines that support other
character sets (like EBCDIC) have different values. For the program to be independent of the
character set, we need to store the difference of these two values in a separate variable (diff).
We can then derive the lowercase value of a letter from knowledge of its uppercase value.
The program is portable because instead of using chr + 32, we have used chr + diff.
The for loop initializes the key variable chr to ‘A’ before it evaluates the control expression
chr <= ‘Z’. Since this is true and will remain true for the next 25 iterations, the loop is entered.
Next, printf prints the value of ‘a’ in a space 3 characters wide (because of %3hd) before beginning
the next iteration. A simple equality test in the loop ensures the printing of nine entries in each line.
After completing one iteration, control moves to the top where chr is incremented and the control
expression re-evaluated. The entire cycle is repeated until the value of chr exceeds ‘Z’, when the
loop terminates. However, in every ninth iteration, printf prints a newline and count is reset to zero.
256 Computer Fundamentals & C Programming

Tip: When designing programs that change the case of letters, follow the preceding technique
of storing the difference between a lowercase and uppercase letter in a variable, and then use
this value for case conversion. Your programs won’t be portable if you derive the value of ‘a’ by
adding 32 to ‘A’ simply because this relation is true only for ASCII systems.

8.10.2 print_terms.c: Completing a Series of Mathematical Expressions


You can use a for loop to complete a series comprising expressions (terms) where a fixed relation
exists between two consecutive terms. Consider the following series comprising the squares of
consecutive integers where the odd terms are added and even terms are subtracted:
1 - 4 + 9 - 16 + 25 ...

The nth term in the series is represented as n2. The following program (Program 8.12) completes the
series up to n terms where n is set by the user. The program also evaluates the complete expression
by choosing the + and - operators correctly. The annotations adequately explain the working of
the program.

/* print_terms.c: Program to complete a series of squares of integers.


Adds even terms but subtracts odd terms. */
#include<stdio.h>
int main(void)
{
short n, n_max, sum = 0;
printf(“Enter max number of terms: “);
scanf(“%hd”, &n_max);
for (n = 1; n <= n_max; n++) {
if (n % 2 == 0) /* For even integers ... */
sum += n * n; /* ... add to sum */
else /* For odd integers ... */
sum -= n * n; /* ... subtract from sum */
printf(“%hd “, n * n); /* Displays square of integer */
}
printf(“\nSum = %hd\n”, sum);
return 0;
}

PROGRAM 8.12: print_terms.c


Enter max number of terms: 5
1 4 9 16 25
Sum = -15
Enter max number of terms: 10
1 4 9 16 25 36 49 64 81 100
Sum = 55

PROGRAM OUTPUT: print_terms.c


Control Structures—Loops 257

8.11 for: THE THREE EXPRESSIONS (exp1, exp2, exp3)


Each component of the combined expression exp1; exp2; exp3 need not be a single expression.
You can use a comma-operated expression to represent any of these expressions. You can drop any
expression or take the extreme step of dropping all of them! The following paragraphs discuss some
of the ways these three expressions can be tweaked to our advantage.

8.11.1 Moving All Initialization to exp1


To appreciate the usefulness of the comma operator, have a look at the two initializations made
before the loop in the program ascii_letters.c (Program 8.11):
diff = ‘a’ - ‘A’;
count = 0;
Since exp1 is evaluated only in the first iteration, there’s no reason why we can’t move these
assignments to exp1. The for statement should now look like this:
for (diff = ‘a’ - ‘A’, count = 0, chr = ‘A’; chr <= ‘Z’; chr++)

The value of exp1 (containing the two comma operators) is now ‘A’ (the value of the right-most
expression), but that is of no consequence to us in this program. What matters to us is that the
three expressions together can be treated as exp1.

8.11.2 Moving Expression Statements in Body to exp3


Let’s now consider the program, while_intro.c (Program 8.1), which adds the first 10 integers
using a while loop. The equivalent code using for is shown below:
short i, sum;
for (i = 1, sum = 0; i <= 10; i++) {
sum += i;
printf(“%hd “, sum);
}
printf(“\nSum of first 10 integers = %hd\n”, sum); Prints 55
The loop body contains two statements, which along with i++ (exp3), constitute the body of the
equivalent while loop. So if i++ can represent exp3, why not sum += i? Yes, we can move this
operation to exp3, but we also need to change two things: initialize i to 0 (instead of 1) and change
the relational operator to < (instead of <=):
for (i = 0, sum = 0; i < 10; ++i, sum += i)
printf(“%hd “, sum); Also prints 55
But then printf is also an expression, so why leave it out?
for (i = 0, sum = 0; i < 100; ++i, sum += i, printf(“%hd “, sum))
; Also prints 55
This for loop has no body as shown by the null statement (the solitary ;) on a separate line. This ;
is necessary, otherwise the subsequent printf statement will be considered as the body of the loop,
which it is not.
258 Computer Fundamentals & C Programming

8.11.3 Dropping One or More Expressions


Program 8.13 uses the scanf function to convert a line of keyboard input from lower- to uppercase.
This function, when used with %c, saves the fetched character in a char variable. The for loop in
this program has a component missing, while the other two components are unrelated.

/* lower2upper.c: Converts a line of keyboard input to uppercase. */


#include <stdio.h>
int main(void)
{
char c, diff;
for (diff = ‘a’ - ‘A’; scanf(“%c”, &c) == 1; ) {
if (c >= ‘a’ && c <= ‘z’)
printf(“%c”, c - diff);
else
printf(“%c”, c);
}
return 0;
}

PROGRAM 8.13: lower2upper.c


dont forget to use the & prefix with the variables used in scanf.
DONT FORGET TO USE THE & PREFIX WITH THE VARIABLES USED IN SCANF.
[Ctrl-d]
PROGRAM OUTPUT: lower2upper.c

The expression exp2 of this for loop behaves in an unusual manner. Every iteration of the loop
runs scanf to assign the next input character to the variable c. The loop thus reads a complete
line of input and terminates when it encounters EOF. Because there is no key variable here,
we don’t need to use exp3 at all. Its absence is indicated by the solitary ; at the end of the complete
expression. Like Program 8.11, this program is also portable.
Note: The return value of the scanf expression acts as a key variable in this program. Its side effect
is also utilized by the program.

8.11.4 The Infinite Loop


Depending on the nature of the problem, any of the three expressions can be dropped. As a special
case, all of them can be dropped to create an infinite loop:
for (;;) Infinite loop; like while (1)
Though this isn’t quite intuitive, the absence of all expressions signifies a perpetually true condition.
Since exp2 needs to be permanently true, the statement for (;1;) also creates an infinite loop, but
for (;0;) doesn’t. Like in the while loop, any infinite loop can be terminated with break.
Control Structures—Loops 259

Note: In most cases, the for loop uses the same variable as the three components of the combined
expression. However, this is not the case in Program 8.13; the variables diff and c are completely
unrelated to each other. Be prepared to see for loops where exp1, exp2 and exp3 are represented by
three different variables.

8.12 decimal2binary2.c: CONVERTING A DECIMAL NUMBER TO BINARY


Program 8.14 is an improved version of its predecessor (Program 8.10). It saves in an array the
remainders generated by repeated division of a number by 2. The program then reverse-reads the
array to generate the binary equivalent of the decimal integer. The program uses two for loops for
saving and reading the bits.

/* decimal2binary2.c: Stores remainders generated by repeated integer


division in an array and then reverse-reads the array. */
#include <stdio.h>
int main(void)
{
unsigned long quot;
char binary_digits[80]; /* Adequate for remainders of 80 divisions */
short rem, index;
printf(“Enter a decimal integer: “);
scanf(“%lu”, &quot);
for (index = 0; quot > 0; index++, quot /= 2) {
rem = quot % 2;
binary_digits[index] = rem == 1 ? ‘1’ : ‘0’;
}
/* All remainders stored ... */
for (index--; index >= 0; index--) /* ... Now reverse-read the array. */
printf(“%c “, binary_digits[index]);
return 0;
}

PROGRAM 8.14: decimal2binary2.c


Enter a decimal integer: 8
1 0 0 0
Enter a decimal integer: 35
1 0 0 0 1 1
Enter a decimal integer: 128
1 0 0 0 0 0 0 0

PROGRAM OUTPUT: decimal2binary2.c


260 Computer Fundamentals & C Programming

Repeated division by 2 in the first for loop generates the values 0 and 1 of type short. Because the
array, binary_digits, is of type char, these short values are transformed to char using a conditional
expression. After the first for loop has completed its run, binary_digits has all the remainders.
A second for loop now reads this array backwards by repeatedly decrementing the value of index
which was set by the previous loop.

8.13 NESTED for LOOPS


One for loop can enclose any number of inner for loops. For reasons of compactness, nested for
loops are often preferred to nested while loops. For instance, the multiplication table created with
a nested while loop in Section 8.5.1 can also be printed with a compact nested for loop structure.
In the following equivalent construct, for each value of x (1 to 5), y can take on 12 values (1 to 12):
int x, y;
for (x = 1; x <= 5; x++) {
for (y = 1; y <= 12; y++)
printf(“ %3d”, x * y);
printf(“\n”);
}
Nested for loops are the perfect tool to use for printing patterns. We have used nested while loops
to print a half-pyramid (Program 8.6), so let’s use a nested for loop to print a complete pyramid
with asterisks. Program 8.15 prints the following pattern when the number of rows is set to 6 by
user input:
*
***
*****
*******
*********
***********

/* pyramid.c: Prints a pyramid pattern with the * using nested for loops. */
#include <stdio.h>
int main(void)
{
short i, j, k, rows;
printf(“Number of rows? “);
scanf(“%hd”, &rows);
for (i = 1; i <= rows; i++) {
for (j = 1; j <= rows - i; j++)
printf(“ “); /* Prints spaces before pattern */
for (k = 0; k != 2 * i - 1; k++)
printf(“*”);
printf(“\n”);
}
return 0;
}

PROGRAM 8.15: pyramid.c


Control Structures—Loops 261

Each line is printed by increasing the number of asterisks by 2 and decreasing the number of leading
spaces by 1. This logic is captured by the control expressions of two for loops in Program 8.15.
The expression j <= rows - 1 controls the number of spaces, and the expression k != 2 * i - 1
controls the number of asterisks.

8.14 USING for WITH break AND continue


The keywords, break and continue , apply to all loops including for. break terminates the current
loop and moves control to the statement following the end of the loop. continue suspends the
current iteration to start the next iteration. Figure 8.8 shows small code fragments that highlight
their usage in the for loop.
You have already experienced the convenience of using break and continue in a while loop. It’s
clear that, without them, one would need to use additional code to bypass subsequent processing.
You would need to set special flags to force the control expression to change normal loop behavior
(8.6). A previous caveat applies here as well: a break statement in the inner loop can’t take control
out of the enclosing loop.

for (div = 3; div < num; div += 2) { for (;;) {


if (num % div == 0) { printf(“Number for prime test: “);
is_prime = ‘n’; scanf(“%d”, &number);
break; if (number < 0) {
} printf(“Invalid input\n”);
} continue;
}
... rest of code ...
FIGURE 8.8 Use of break and continue in a for Loop

8.15 all_prime_numbers.c: USING break AND continue


The final program of this chapter (Program 8.16) generates all prime numbers not exceeding
a user-set limit. In Program 8.9, we determined whether a number is prime by dividing it by all
smaller integers. That program unnecessarily included even numbers but the current program skips
them. For reasons of convenience, the program doesn’t print 2, the first prime number.
This program considers only odd values of both divisor and dividend. The outer for loop cycles
through odd values of the dividend and the inner loop does the same for the divisor. The program
works on the principle that a number is prime unless proved otherwise.
262 Computer Fundamentals & C Programming

/* all_prime_numbers.c: Uses a nested for loop to generate all prime numbers


not exceeding a user-set limit. Starts from 3. */
#include <stdio.h>
int main(void)
{
int num, max_num, div;
char is_prime;
printf(“Maximum number to be tested for prime: “);
scanf(“%d”, &max_num);
for (num = 3; num <= max_num; num += 2) { /* Tests odd integers only */
is_prime = ‘y’;
for (div = 3; div < num; div += 2) { /* Divisor is also odd */
if (num % div == 0) {
is_prime = ‘n’; /* Number is not prime so ... */
break; /* no further check required */
}
}
if (is_prime == ‘y’) /* If prime number found ... */
printf(“%d “, num); /* ... print it */
}
printf(“\n”);
return 0;
}

PROGRAM 8.16: all_prime_numbers.c


Maximum number to be tested for prime: 100
3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

PROGRAM OUTPUT: all_prime_numbers.c

WHAT NEXT?

All work in C is performed by functions, and we must know the ones that interact with the terminal.
The next chapter makes a detailed examination of the essential input/output (I/O) functions.

WHAT DID YOU LEARN?

A loop generally operates by first initializing a key variable, testing it in the control expression and
then updating it in the loop body.
A loop may run a finite or infinite number of times. An infinite loop is created if the control expression
never turns false.

You might also like