Control Structures in C¶
Control structures in C programming are used to control the flow of program execution. They determine how the statements in a program are executed based on certain conditions. The basic control structures in C can be categorized into three types: Sequence, Selection, and Iteration.
Sequence Structure¶
The sequence structure is the simplest of all control structures. In this structure, statements are executed in the order they appear in the program. There is no skipping or repeating of statements.
Example:
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
int sum = a + b; // Sequential execution
printf("Sum: %d\n", sum);
return 0;
}
Selection Structure¶
Selection structures allow the program to execute different blocks of code based on certain conditions. The selection structures in C include if-else statements and switch-case statements.
Conditional Statements¶
if-else statement¶
The if statement is used to execute a block of code only if a specified condition evaluates to true. The else statement specifies a block of code to be executed if the condition is false.
Basic 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 num = 10;
if (num > 0) {
printf("Number is positive\n");
} else {
printf("Number is not positive\n");
}
return 0;
}
if-else if-else ladder¶
For multiple conditions, we can use the if-else if-else ladder:
if (condition1) {
// Code if condition1 is true
} else if (condition2) {
// Code if condition2 is true
} else {
// Code if all conditions are false
}
Nested conditions¶
Conditions can be nested within other conditions:
if (condition1) {
if (condition2) {
// Code to execute if both conditions are true
} else {
// Code to execute if condition1 is true and condition2 is false
}
} else {
// Code to execute if condition1 is false
}
Example of nested conditions:
#include <stdio.h>
int main() {
int num = 15;
if (num > 0) {
if (num % 2 == 0) {
printf("Positive even number\n");
} else {
printf("Positive odd number\n");
}
} else {
printf("Not a positive number\n");
}
return 0;
}
switch-case statement¶
The switch statement is used to perform different actions based on different conditions. It's often cleaner than multiple if-else statements when you have many conditions to check.
Basic syntax:
switch (expression) {
case constant1:
// Code to execute
break;
case constant2:
// Code to execute
break;
default:
// Code to execute if no case matches
}
Example:
#include <stdio.h>
int main() {
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
default:
printf("Invalid day\n");
}
return 0;
}
Important notes about switch-case:
- The expression in the switch must be an integer or character
- Each case must end with a break statement, otherwise execution will "fall through" to the next case
- The default case is optional and executes if no case matches
Iteration Structure¶
Iteration structures (loops) allow a block of code to be executed repeatedly under certain conditions. The loop structures in C include for loop, while loop, and do-while loop.
for loop¶
The for loop is used when you know how many times you want to execute a block of code.
Basic syntax:
for (initialization; condition; increment/decrement) {
// Code to execute in each iteration
}
Example:
#include <stdio.h>
int main() {
for (int i = 0; i < 5; i++) {
printf("Iteration %d\n", i);
}
return 0;
}
Using for loop for counting iterations:
#include <stdio.h>
int main() {
int sum = 0;
for (int i = 1; i <= 10; i++) {
sum += i;
}
printf("Sum of numbers 1 to 10: %d\n", sum);
return 0;
}
while loop¶
The while loop is used when you want to execute a block of code as long as a condition is true. It's useful for indefinite iterations.
Basic syntax:
while (condition) {
// Code to execute while condition is true
}
Example:
#include <stdio.h>
int main() {
int count = 0;
while (count < 5) {
printf("Count: %d\n", count);
count++;
}
return 0;
}
Using while loop for indefinite iterations:
#include <stdio.h>
int main() {
int number;
while (1) { // Infinite loop
printf("Enter a positive number (0 to exit): ");
scanf("%d", &number);
if (number == 0) {
break;
}
if (number > 0) {
printf("You entered: %d\n", number);
} else {
printf("Please enter a positive number\n");
}
}
printf("Program ended.\n");
return 0;
}
do-while loop¶
The do-while loop is similar to the while loop, but it executes the code block at least once before checking the condition.
Basic syntax:
do {
// Code to execute
} while (condition);
Example:
#include <stdio.h>
int main() {
int number = 0;
do {
printf("Enter a number (0 to exit): ");
scanf("%d", &number);
printf("You entered: %d\n", number);
} while (number != 0);
return 0;
}
Nested loops¶
Loops can be nested inside other loops. This is useful for handling multidimensional data or patterns.
Example:
#include <stdio.h>
int main() {
for (int i = 1; i <= 3; i++) {
printf("Outer loop iteration %d:\n", i);
for (int j = 1; j <= 3; j++) {
printf(" Inner loop iteration %d\n", j);
}
}
return 0;
}
Pattern using nested loops:
#include <stdio.h>
int main() {
int rows = 5;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
printf("* ");
}
printf("\n");
}
return 0;
}
Break and Continue Statements¶
break statement¶
The break statement is used to terminate the current loop or switch statement and transfer control to the statement immediately following the loop or switch.
Example with loop:
#include <stdio.h>
int main() {
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // Exit loop when i equals 5
}
printf("%d ", i);
}
printf("\nLoop terminated with break statement.\n");
return 0;
}
continue statement¶
The continue statement is used to skip the current iteration of a loop and move to the next iteration.
Example:
#include <stdio.h>
int main() {
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
continue; // Skip even numbers
}
printf("%d ", i);
}
printf("\nOnly odd numbers printed.\n");
return 0;
}
Compare break and continue:¶
- break: Exits the loop entirely
- continue: Skips the current iteration and continues with the next one
Example demonstrating both:
#include <stdio.h>
int main() {
printf("Using break:\n");
for (int i = 0; i < 5; i++) {
if (i == 2) {
break;
}
printf("%d ", i);
}
printf("\n\nUsing continue:\n");
for (int i = 0; i < 5; i++) {
if (i == 2) {
continue;
}
printf("%d ", i);
}
return 0;
}
Control Flow Diagrams¶
Control structures can be better understood through flow diagrams. Here's a simple representation of decision and loop structures:
[insert flowchart decision and loop control structures here]
Common Pitfalls and Best Practices¶
- Infinite loops: Always ensure loop conditions can be met to avoid infinite loops
- Missing semicolons: In loops and conditionals, missing a semicolon can lead to syntax errors
- Off-by-one errors: Be careful with comparison operators (<, <=, >, >=) to avoid executing one more or one less iteration than intended
- Uninitialized variables: Using uninitialized variables in loop conditions can lead to unpredictable behavior
- Break vs. continue: Understand the difference to control loop execution appropriately
Advanced Topics¶
Loop Optimization¶
For performance-critical applications, consider:
- Minimizing operations inside loops
- Using appropriate loop constructs
- Avoiding unnecessary computations inside loops
Example of optimization:
// Less optimized - calculation inside loop
int sum1 = 0;
for (int i = 0; i < 1000; i++) {
sum1 += i * 2 + 5;
}
// More optimized - calculation outside loop
int multiplier = 2;
int addend = 5;
int sum2 = 0;
for (int i = 0; i < 1000; i++) {
sum2 += i * multiplier + addend;
}
Loop Unrolling¶
Loop unrolling is a technique where the number of loop iterations is decreased by increasing the number of operations performed in each iteration. This can improve performance by reducing loop overhead.
Example:
// Standard loop
for (int i = 0; i < 10; i++) {
process_array[i] = i * 2;
}
// Unrolled loop
for (int i = 0; i < 10; i += 2) {
process_array[i] = i * 2;
process_array[i+1] = (i+1) * 2;
}