Chapter 3: Control Flow: Decisions and Loops
In the previous chapter, you learned how to store and manipulate data. But what if you want your program to make choices or repeat actions? This is where control flow comes in. Control flow statements dictate the order in which individual instructions or statements are executed.
In C, the primary control flow mechanisms are:
- Conditional Statements: For making decisions (e.g., “if this is true, do that; otherwise, do something else”).
- Looping Statements: For repeating a block of code multiple times.
Mastering control flow is essential for writing dynamic and intelligent programs.
3.1 Conditional Statements (Decision Making)
Conditional statements allow your program to execute different blocks of code based on whether a specified condition is true or false.
3.1.1 Relational and Logical Operators
Before we dive into if statements, let’s understand the operators used to form conditions.
Relational Operators: Used to compare two operands. They return true (non-zero, typically 1) or false (0).
| Operator | Description | Example (a=5, b=10) | Result |
|---|---|---|---|
== | Equal to | a == b | false (0) |
!= | Not equal to | a != b | true (1) |
> | Greater than | a > b | false (0) |
< | Less than | a < b | true (1) |
>= | Greater than or equal to | a >= b | false (0) |
<= | Less than or equal to | a <= b | true (1) |
Important: Do not confuse the assignment operator = with the equality operator ==. Using = where == is intended is a common bug in C!
Logical Operators: Used to combine or modify conditional expressions.
| Operator | Description | Example (cond1, cond2 are conditions) | Result |
|---|---|---|---|
&& | Logical AND | cond1 && cond2 | true if BOTH are true |
| ` | ` | Logical OR | |
! | Logical NOT | !cond1 | true if cond1 is false |
Truthiness in C:
In C, any non-zero value is considered true, and 0 is considered false. When relational or logical operators evaluate to true, they typically produce 1.
3.1.2 The if Statement
The simplest conditional statement.
Syntax:
if (condition) {
// Code to execute if condition is true
}
If the if statement body contains only a single statement, the curly braces {} are optional, but it’s good practice to always use them for clarity and to avoid potential bugs.
Example:
#include <stdio.h>
int main() {
int temperature = 25;
if (temperature > 20) {
printf("It's a warm day!\n");
}
return 0;
}
3.1.3 The if-else Statement
Executes one block of code if the condition is true, and another if it’s false.
Syntax:
if (condition) {
// Code to execute if condition is true
} else {
// Code to execute if condition is false
}
Example:
#include <stdio.h>
int main() {
int hour = 14; // 2 PM
if (hour < 12) {
printf("Good morning!\n");
} else {
printf("Good afternoon!\n");
}
return 0;
}
3.1.4 The if-else if-else Ladder
Used when you have multiple conditions to check in sequence.
Syntax:
if (condition1) {
// Code if condition1 is true
} else if (condition2) {
// Code if condition2 is true
} else if (condition3) {
// Code if condition3 is true
} else {
// Code if none of the above conditions are true
}
Example:
#include <stdio.h>
int main() {
int score = 75;
char grade;
if (score >= 90) {
grade = 'A';
} else if (score >= 80) {
grade = 'B';
} else if (score >= 70) {
grade = 'C';
} else if (score >= 60) {
grade = 'D';
} else {
grade = 'F';
}
printf("Your grade is: %c\n", grade); // Output: Your grade is: C
return 0;
}
3.1.5 Nested if Statements
You can place if or if-else statements inside other if or else blocks.
Example:
#include <stdio.h>
int main() {
int age = 20;
int has_license = 1; // 1 for true, 0 for false
if (age >= 18) {
printf("You are old enough to drive.\n");
if (has_license) {
printf("You have a driver's license! You can drive.\n");
} else {
printf("But you don't have a license yet. Get one!\n");
}
} else {
printf("You are not old enough to drive.\n");
}
return 0;
}
3.1.6 The switch Statement
The switch statement is an alternative to a long if-else if-else ladder when you are comparing a single variable against multiple constant integer values (characters are treated as integers).
Syntax:
switch (expression) { // expression must evaluate to an integer type
case constant_value1:
// Code to execute if expression == constant_value1
break; // Important: exits the switch statement
case constant_value2:
// Code to execute if expression == constant_value2
break;
// ... more cases
default:
// Code to execute if no case matches (optional)
break;
}
Key Points:
- The
expressionmust be an integer type (or convertible to one, likechar). caselabels must be unique constant integer expressions.- The
breakstatement is crucial. Without it, execution “falls through” to the nextcaselabel, which is rarely desired and a common source of bugs. - The
defaultcase is optional and executes if no othercasematches.
Example:
#include <stdio.h>
int main() {
char operator = '+';
double num1 = 10.0, num2 = 5.0;
double result;
switch (operator) {
case '+':
result = num1 + num2;
printf("%.1lf + %.1lf = %.1lf\n", num1, num2, result);
break;
case '-':
result = num1 - num2;
printf("%.1lf - %.1lf = %.1lf\n", num1, num2, result);
break;
case '*':
result = num1 * num2;
printf("%.1lf * %.1lf = %.1lf\n", num1, num2, result);
break;
case '/':
if (num2 != 0) { // Good practice: prevent division by zero
result = num1 / num2;
printf("%.1lf / %.1lf = %.1lf\n", num1, num2, result);
} else {
printf("Error: Division by zero!\n");
}
break;
default:
printf("Error: Invalid operator!\n");
break;
}
return 0;
}
Exercise 3.1: Grade Calculator
Write a C program that prompts the user to enter a percentage score (an integer). Then, using if-else if-else statements, determine and print the corresponding letter grade based on the following scale:
- 90-100: A
- 80-89: B
- 70-79: C
- 60-69: D
- 0-59: F
Hint: You’ll need to use scanf() to get user input. Here’s a quick example:
#include <stdio.h>
int main() {
int input_score;
printf("Enter your score (0-100): ");
scanf("%d", &input_score); // Reads an integer from the console
// Your if-else if-else logic here
return 0;
}
Important: The & before input_score in scanf is crucial; it means “address of”. We’ll learn more about this when we cover pointers. For now, just know it’s necessary for scanf to work.
Exercise 3.2: Simple Traffic Light Logic
Simulate a traffic light. Declare a char variable light_color and assign it one of 'R' (red), 'Y' (yellow), or 'G' (green). Use a switch statement to print an appropriate action based on the color:
- ‘R’: “Stop! Do not proceed.”
- ‘Y’: “Caution! Prepare to stop or clear intersection.”
- ‘G’: “Go! Proceed safely.”
- Any other: “Invalid light color.”
3.2 Looping Statements (Repetition)
Loops allow you to execute a block of code repeatedly as long as a certain condition is met. This is fundamental for tasks like processing lists of data, counting, or waiting for an event.
3.2.1 The while Loop
The while loop repeatedly executes a block of code as long as its condition remains true. The condition is checked before each iteration.
Syntax:
while (condition) {
// Code to execute repeatedly
// Make sure something inside the loop changes the condition to eventually become false,
// otherwise you'll have an infinite loop!
}
Example:
#include <stdio.h>
int main() {
int count = 1;
while (count <= 5) {
printf("Count: %d\n", count);
count++; // Increment count, eventually making the condition false
}
printf("Loop finished. Final count: %d\n", count); // Output: 6
return 0;
}
3.2.2 The do-while Loop
Similar to the while loop, but the code block is executed at least once before the condition is checked.
Syntax:
do {
// Code to execute at least once, then repeatedly
} while (condition); // Note the semicolon here!
Example:
#include <stdio.h>
int main() {
int num = 0;
do {
printf("Enter a positive number: ");
scanf("%d", &num);
} while (num <= 0); // Keep asking until a positive number is entered
printf("You entered: %d\n", num);
return 0;
}
3.2.3 The for Loop
The for loop is ideal when you know exactly how many times you want to loop, or when you have a clear initialization, condition, and iteration step.
Syntax:
for (initialization; condition; update) {
// Code to execute repeatedly
}
- Initialization: Executed once at the beginning of the loop. Typically used to declare and initialize a loop counter.
- Condition: Checked before each iteration. If true, the loop continues; if false, the loop terminates.
- Update: Executed after each iteration. Typically used to increment or decrement the loop counter.
Example:
#include <stdio.h>
int main() {
printf("Counting from 1 to 5:\n");
for (int i = 1; i <= 5; i++) {
printf("%d\n", i);
}
printf("\nCounting down from 10 to 1:\n");
for (int j = 10; j > 0; j--) {
printf("%d\n", j);
}
return 0;
}
3.2.4 break and continue Statements
These statements allow you to modify the normal flow of loops.
break: Terminates the innermost loop (orswitchstatement) immediately and transfers control to the statement immediately following the loop.continue: Skips the rest of the current iteration of the innermost loop and proceeds to the next iteration (checks the condition, then performs the update forforloops).
Example:
#include <stdio.h>
int main() {
printf("--- Using break ---\n");
for (int i = 1; i <= 10; i++) {
if (i == 6) {
printf("Breaking loop at i = %d\n", i);
break; // Exit the loop entirely
}
printf("%d ", i);
}
printf("\nLoop after break has ended.\n"); // Output: 1 2 3 4 5 Breaking loop at i = 6 Loop after break has ended.
printf("\n--- Using continue ---\n");
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) { // If i is even
continue; // Skip the rest of this iteration, go to next i
}
printf("%d ", i);
}
printf("\nLoop after continue has ended.\n"); // Output: 1 3 5 7 9 Loop after continue has ended.
return 0;
}
Exercise 3.3: Sum of Numbers
Write a C program that calculates the sum of all integers from 1 to 100 using a for loop. Print the final sum.
Exercise 3.4: Guess the Number Game (Mini-Challenge)
Create a simple “Guess the Number” game.
Instructions:
- Generate a random number between 1 and 100. (You’ll need
<stdlib.h>forrand()and<time.h>forsrand()to seed the random number generator. A common pattern issrand(time(NULL)); int target = (rand() % 100) + 1;). - Use a
do-whileloop to repeatedly:- Prompt the user to guess a number.
- Read the user’s guess using
scanf(). - If the guess is too high, print “Too high! Try again.”
- If the guess is too low, print “Too low! Try again.”
- If the guess is correct, print “Congratulations! You guessed the number in X tries.” (Keep a counter for tries).
- The loop should continue until the correct number is guessed.
Hint for random numbers:
#include <stdlib.h> // For rand(), srand()
#include <time.h> // For time()
int main() {
srand(time(NULL)); // Seed the random number generator once at the start
int target_number = (rand() % 100) + 1; // Generates a number from 1 to 100
// ... rest of your game logic
return 0;
}
This chapter provided you with the essential tools for making your C programs interactive and dynamic. You now know how to use conditional statements to handle different scenarios and how to use loops to perform repetitive tasks efficiently. In the next chapter, we’ll learn about functions, which are critical for organizing your code into reusable and manageable blocks.