Introduction to Nested Loops
Nested loops are loops inside other loops. They are essential for working with multi-dimensional data, creating patterns, and solving problems that require repeated operations within iterations. Understanding nested loops is crucial for matrix operations, pattern printing, and complex algorithmic problems.
Nested Loop Architecture
Nested Loop Structure ├── Outer Loop │ ├── Controls rows / major iterations │ ├── Executes less frequently │ └── Sets context for inner loop ├── Inner Loop │ ├── Controls columns / minor iterations │ ├── Executes completely for each outer iteration │ └── Performs detailed operations └── Loop Body ├── Operations performed at each inner iteration └── Can access both loop counters
Basic Nested Loop Syntax
Nested for Loop
#include <stdio.h>
int main() {
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 4; j++) {
printf("(%d,%d) ", i, j);
}
printf("\n"); // New line after each row
}
return 0;
}
Output:
(1,1) (1,2) (1,3) (1,4) (2,1) (2,2) (2,3) (2,4) (3,1) (3,2) (3,3) (3,4)
Nested while Loop
#include <stdio.h>
int main() {
int i = 1;
while (i <= 3) {
int j = 1;
while (j <= 4) {
printf("%d,%d ", i, j);
j++;
}
printf("\n");
i++;
}
return 0;
}
Nested do-while Loop
#include <stdio.h>
int main() {
int i = 1;
do {
int j = 1;
do {
printf("%d,%d ", i, j);
j++;
} while (j <= 4);
printf("\n");
i++;
} while (i <= 3);
return 0;
}
Mixed Loop Types
#include <stdio.h>
int main() {
// for inside while
int i = 1;
while (i <= 3) {
for (int j = 1; j <= 4; j++) {
printf("%d,%d ", i, j);
}
printf("\n");
i++;
}
printf("\n");
// while inside for
for (int i = 1; i <= 3; i++) {
int j = 1;
while (j <= 4) {
printf("%d,%d ", i, j);
j++;
}
printf("\n");
}
return 0;
}
Pattern Printing with Nested Loops
1. Rectangle Patterns
#include <stdio.h>
int main() {
int rows = 5, cols = 8;
printf("Solid Rectangle (%d x %d):\n", rows, cols);
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
printf("* ");
}
printf("\n");
}
printf("\nHollow Rectangle (%d x %d):\n", rows, cols);
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
if (i == 1 || i == rows || j == 1 || j == cols) {
printf("* ");
} else {
printf(" ");
}
}
printf("\n");
}
return 0;
}
Output:
Solid Rectangle (5 x 8): * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Hollow Rectangle (5 x 8): * * * * * * * * * * * * * * * * * * * * * *
2. Triangle Patterns
#include <stdio.h>
int main() {
int n = 5;
printf("Right Triangle (Increasing):\n");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
printf("* ");
}
printf("\n");
}
printf("\nRight Triangle (Decreasing):\n");
for (int i = n; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
printf("* ");
}
printf("\n");
}
printf("\nInverted Right Triangle:\n");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
for (int k = 1; k <= i; k++) {
printf("* ");
}
printf("\n");
}
return 0;
}
Output:
Right Triangle (Increasing): * * * * * * * * * * * * * * * Right Triangle (Decreasing): * * * * * * * * * * * * * * * Inverted Right Triangle: * * * * * * * * * * * * * * *
3. Pyramid Patterns
#include <stdio.h>
int main() {
int n = 5;
printf("Full Pyramid:\n");
for (int i = 1; i <= n; i++) {
// Print spaces
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
// Print stars
for (int k = 1; k <= 2 * i - 1; k++) {
printf("* ");
}
printf("\n");
}
printf("\nHollow Pyramid:\n");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
for (int k = 1; k <= 2 * i - 1; k++) {
if (k == 1 || k == 2 * i - 1 || i == n) {
printf("* ");
} else {
printf(" ");
}
}
printf("\n");
}
printf("\nNumber Pyramid:\n");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
for (int k = 1; k <= i; k++) {
printf("%d ", k);
}
for (int k = i - 1; k >= 1; k--) {
printf("%d ", k);
}
printf("\n");
}
return 0;
}
Output:
Full Pyramid: * * * * * * * * * * * * * * * * * * * * * * * * * Hollow Pyramid: * * * * * * * * * * * * * * * * Number Pyramid: 1 1 2 1 1 2 3 2 1 1 2 3 4 3 2 1 1 2 3 4 5 4 3 2 1
4. Diamond Pattern
#include <stdio.h>
int main() {
int n = 5;
printf("Diamond Pattern:\n");
// Upper half
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
for (int k = 1; k <= 2 * i - 1; k++) {
printf("* ");
}
printf("\n");
}
// Lower half
for (int i = n - 1; i >= 1; i--) {
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
for (int k = 1; k <= 2 * i - 1; k++) {
printf("* ");
}
printf("\n");
}
return 0;
}
Output:
Diamond Pattern: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Matrix Operations with Nested Loops
1. Matrix Addition
#include <stdio.h>
#define ROWS 3
#define COLS 3
int main() {
int A[ROWS][COLS] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int B[ROWS][COLS] = {
{9, 8, 7},
{6, 5, 4},
{3, 2, 1}
};
int C[ROWS][COLS];
// Matrix addition
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
C[i][j] = A[i][j] + B[i][j];
}
}
// Print result
printf("Matrix A + Matrix B = \n");
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
printf("%4d ", C[i][j]);
}
printf("\n");
}
return 0;
}
Output:
Matrix A + Matrix B = 10 10 10 10 10 10 10 10 10
2. Matrix Multiplication
#include <stdio.h>
#define ROWS_A 2
#define COLS_A 3
#define ROWS_B 3
#define COLS_B 2
int main() {
int A[ROWS_A][COLS_A] = {
{1, 2, 3},
{4, 5, 6}
};
int B[ROWS_B][COLS_B] = {
{7, 8},
{9, 10},
{11, 12}
};
int C[ROWS_A][COLS_B] = {0};
// Matrix multiplication
for (int i = 0; i < ROWS_A; i++) {
for (int j = 0; j < COLS_B; j++) {
for (int k = 0; k < COLS_A; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
// Print matrices
printf("Matrix A (%d x %d):\n", ROWS_A, COLS_A);
for (int i = 0; i < ROWS_A; i++) {
for (int j = 0; j < COLS_A; j++) {
printf("%4d ", A[i][j]);
}
printf("\n");
}
printf("\nMatrix B (%d x %d):\n", ROWS_B, COLS_B);
for (int i = 0; i < ROWS_B; i++) {
for (int j = 0; j < COLS_B; j++) {
printf("%4d ", B[i][j]);
}
printf("\n");
}
printf("\nMatrix A * Matrix B = \n");
for (int i = 0; i < ROWS_A; i++) {
for (int j = 0; j < COLS_B; j++) {
printf("%4d ", C[i][j]);
}
printf("\n");
}
return 0;
}
3. Matrix Transpose
#include <stdio.h>
#define ROWS 3
#define COLS 4
int main() {
int matrix[ROWS][COLS] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int transpose[COLS][ROWS];
// Transpose the matrix
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
transpose[j][i] = matrix[i][j];
}
}
// Print original matrix
printf("Original Matrix (%d x %d):\n", ROWS, COLS);
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
printf("%4d ", matrix[i][j]);
}
printf("\n");
}
// Print transpose
printf("\nTranspose Matrix (%d x %d):\n", COLS, ROWS);
for (int i = 0; i < COLS; i++) {
for (int j = 0; j < ROWS; j++) {
printf("%4d ", transpose[i][j]);
}
printf("\n");
}
return 0;
}
Number Patterns
1. Floyd's Triangle
#include <stdio.h>
int main() {
int n = 5;
int num = 1;
printf("Floyd's Triangle:\n");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
printf("%3d ", num++);
}
printf("\n");
}
return 0;
}
Output:
Floyd's Triangle: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2. Pascal's Triangle
#include <stdio.h>
// Function to calculate binomial coefficient
int binomial(int n, int k) {
if (k == 0 || k == n)
return 1;
return binomial(n - 1, k - 1) + binomial(n - 1, k);
}
int main() {
int rows = 6;
printf("Pascal's Triangle:\n");
for (int i = 0; i < rows; i++) {
// Print spaces for alignment
for (int space = 0; space < rows - i - 1; space++) {
printf(" ");
}
// Print numbers
for (int j = 0; j <= i; j++) {
printf("%4d", binomial(i, j));
}
printf("\n");
}
return 0;
}
Output:
Pascal's Triangle: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1
3. Multiplication Table
#include <stdio.h>
int main() {
int size = 10;
printf("Multiplication Table:\n\n");
// Print header
printf(" ");
for (int i = 1; i <= size; i++) {
printf("%4d ", i);
}
printf("\n ");
for (int i = 1; i <= size; i++) {
printf("---- ");
}
printf("\n");
// Print table
for (int i = 1; i <= size; i++) {
printf("%2d |", i);
for (int j = 1; j <= size; j++) {
printf("%4d ", i * j);
}
printf("\n");
}
return 0;
}
Game Boards with Nested Loops
1. Chess Board Pattern
#include <stdio.h>
int main() {
int size = 8;
printf("Chess Board Pattern:\n\n");
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if ((i + j) % 2 == 0) {
printf("██ ");
} else {
printf(" ");
}
}
printf("\n");
}
return 0;
}
2. Tic-Tac-Toe Board
#include <stdio.h>
void printBoard(char board[3][3]) {
printf("\n");
for (int i = 0; i < 3; i++) {
printf(" ");
for (int j = 0; j < 3; j++) {
printf("%c", board[i][j]);
if (j < 2) printf(" | ");
}
printf("\n");
if (i < 2) printf("---+---+---\n");
}
printf("\n");
}
int main() {
char board[3][3] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'}
};
printf("Tic-Tac-Toe Board:\n");
printBoard(board);
return 0;
}
Output:
Tic-Tac-Toe Board: 1 | 2 | 3 ---+---+--- 4 | 5 | 6 ---+---+--- 7 | 8 | 9
Algorithmic Problems with Nested Loops
1. Bubble Sort
#include <stdio.h>
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// Swap
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Original array: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
bubbleSort(arr, n);
printf("\nSorted array: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
2. Selection Sort
#include <stdio.h>
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Original array: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
selectionSort(arr, n);
printf("\nSorted array: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
3. Find Duplicates
#include <stdio.h>
void findDuplicates(int arr[], int n) {
printf("Duplicate elements: ");
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (arr[i] == arr[j]) {
printf("%d ", arr[i]);
break;
}
}
}
printf("\n");
}
int main() {
int arr[] = {1, 2, 3, 2, 4, 5, 3, 6, 7, 5};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Array: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
findDuplicates(arr, n);
return 0;
}
4. Prime Numbers in Range
#include <stdio.h>
#include <stdbool.h>
bool isPrime(int num) {
if (num <= 1) return false;
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
void printPrimes(int start, int end) {
printf("Prime numbers between %d and %d:\n", start, end);
for (int i = start; i <= end; i++) {
if (isPrime(i)) {
printf("%d ", i);
}
}
printf("\n");
}
int main() {
printPrimes(10, 50);
return 0;
}
Advanced Nested Loop Techniques
1. Break and Continue in Nested Loops
#include <stdio.h>
int main() {
printf("Break example:\n");
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (i == 2 && j == 2) {
printf("Breaking inner loop at (%d,%d)\n", i, j);
break; // Only breaks inner loop
}
printf("(%d,%d) ", i, j);
}
printf("\n");
}
printf("\nContinue example:\n");
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (i == j) {
printf(" ");
continue; // Skip when i == j
}
printf("%d,%d ", i, j);
}
printf("\n");
}
printf("\nBreaking outer loop using flag:\n");
int found = 0;
for (int i = 1; i <= 3 && !found; i++) {
for (int j = 1; j <= 3; j++) {
if (i == 2 && j == 2) {
printf("Found at (%d,%d) - breaking all loops\n", i, j);
found = 1;
break;
}
printf("(%d,%d) ", i, j);
}
printf("\n");
}
return 0;
}
2. Variable Loop Boundaries
#include <stdio.h>
int main() {
int n = 5;
printf("Upper triangular pattern:\n");
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
printf("* ");
}
printf("\n");
}
printf("\nLower triangular pattern:\n");
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
printf("* ");
}
printf("\n");
}
printf("\nVariable width pattern:\n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - abs(i - n/2); j++) {
printf("* ");
}
printf("\n");
}
return 0;
}
3. Diamond Number Pattern
#include <stdio.h>
int main() {
int n = 5;
printf("Number Diamond:\n\n");
// Upper half
for (int i = 1; i <= n; i++) {
// Spaces
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
// Increasing numbers
for (int j = 1; j <= i; j++) {
printf("%d ", j);
}
// Decreasing numbers
for (int j = i - 1; j >= 1; j--) {
printf("%d ", j);
}
printf("\n");
}
// Lower half
for (int i = n - 1; i >= 1; i--) {
// Spaces
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
// Increasing numbers
for (int j = 1; j <= i; j++) {
printf("%d ", j);
}
// Decreasing numbers
for (int j = i - 1; j >= 1; j--) {
printf("%d ", j);
}
printf("\n");
}
return 0;
}
Performance Considerations
1. Loop Order Optimization
#include <stdio.h>
#include <time.h>
#define SIZE 1000
int main() {
int matrix[SIZE][SIZE];
long long sum = 0;
clock_t start, end;
// Initialize matrix
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
matrix[i][j] = i + j;
}
}
// Row-major order (cache-friendly)
start = clock();
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
sum += matrix[i][j];
}
}
end = clock();
printf("Row-major sum: %lld, Time: %ld ticks\n", sum, end - start);
sum = 0;
// Column-major order (cache-unfriendly)
start = clock();
for (int j = 0; j < SIZE; j++) {
for (int i = 0; i < SIZE; i++) {
sum += matrix[i][j];
}
}
end = clock();
printf("Column-major sum: %lld, Time: %ld ticks\n", sum, end - start);
return 0;
}
2. Loop Unrolling
#include <stdio.h>
#include <time.h>
#define SIZE 1000
int main() {
int arr[SIZE];
int sum1 = 0, sum2 = 0;
clock_t start, end;
// Initialize array
for (int i = 0; i < SIZE; i++) {
arr[i] = i;
}
// Normal loop
start = clock();
for (int i = 0; i < SIZE; i++) {
sum1 += arr[i];
}
end = clock();
printf("Normal loop sum: %d, Time: %ld ticks\n", sum1, end - start);
// Loop unrolled (process 4 elements at a time)
start = clock();
for (int i = 0; i < SIZE; i += 4) {
sum2 += arr[i] + arr[i+1] + arr[i+2] + arr[i+3];
}
end = clock();
printf("Unrolled loop sum: %d, Time: %ld ticks\n", sum2, end - start);
return 0;
}
Common Pitfalls and Solutions
1. Infinite Nested Loops
#include <stdio.h>
int main() {
// WRONG - Infinite loop
// for (int i = 1; i <= 5; i++) {
// int j = 1;
// while (j <= 5) {
// printf("%d,%d ", i, j);
// // Missing j++ -> infinite loop
// }
// }
// CORRECT
for (int i = 1; i <= 5; i++) {
int j = 1;
while (j <= 5) {
printf("%d,%d ", i, j);
j++; // Update counter
}
printf("\n");
}
return 0;
}
2. Off-by-One Errors
#include <stdio.h>
int main() {
int rows = 5;
// WRONG - Prints one extra column
printf("WRONG (off by one):\n");
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= rows; j++) { // Should be j <= i
printf("* ");
}
printf("\n");
}
// CORRECT
printf("\nCORRECT:\n");
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
printf("* ");
}
printf("\n");
}
return 0;
}
3. Uninitialized Variables
#include <stdio.h>
int main() {
// WRONG - sum not initialized
int sum;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
sum += i + j; // sum contains garbage initially
}
}
// CORRECT
int total = 0;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
total += i + j;
}
}
printf("Total: %d\n", total);
return 0;
}
Real-World Applications
1. Image Processing - Simple Grayscale
#include <stdio.h>
#define WIDTH 5
#define HEIGHT 4
void applyGrayscale(int image[HEIGHT][WIDTH]) {
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
// Simulate grayscale conversion
int gray = (image[i][j] * 0.3) + (image[i][j] * 0.59) + (image[i][j] * 0.11);
image[i][j] = gray;
}
}
}
void printImage(int image[HEIGHT][WIDTH], const char *name) {
printf("%s:\n", name);
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
printf("%4d ", image[i][j]);
}
printf("\n");
}
printf("\n");
}
int main() {
int image[HEIGHT][WIDTH] = {
{100, 150, 200, 250, 180},
{120, 170, 220, 230, 190},
{110, 160, 210, 240, 200},
{130, 180, 230, 220, 170}
};
printImage(image, "Original Image");
applyGrayscale(image);
printImage(image, "After Grayscale");
return 0;
}
2. Game of Life Simulation
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ROWS 10
#define COLS 10
void printGrid(int grid[ROWS][COLS]) {
printf("\n");
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
printf("%c ", grid[i][j] ? '■' : '□');
}
printf("\n");
}
}
int countNeighbors(int grid[ROWS][COLS], int x, int y) {
int count = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (i == 0 && j == 0) continue;
int ni = (x + i + ROWS) % ROWS;
int nj = (y + j + COLS) % COLS;
count += grid[ni][nj];
}
}
return count;
}
void nextGeneration(int grid[ROWS][COLS]) {
int newGrid[ROWS][COLS] = {0};
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
int neighbors = countNeighbors(grid, i, j);
if (grid[i][j]) {
// Live cell
newGrid[i][j] = (neighbors == 2 || neighbors == 3) ? 1 : 0;
} else {
// Dead cell
newGrid[i][j] = (neighbors == 3) ? 1 : 0;
}
}
}
// Copy back
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
grid[i][j] = newGrid[i][j];
}
}
}
int main() {
int grid[ROWS][COLS] = {0};
// Initialize with a glider
grid[1][2] = 1;
grid[2][3] = 1;
grid[3][1] = 1;
grid[3][2] = 1;
grid[3][3] = 1;
printf("Conway's Game of Life - Glider Pattern\n");
for (int gen = 0; gen < 10; gen++) {
printf("\nGeneration %d:", gen);
printGrid(grid);
nextGeneration(grid);
usleep(500000); // Sleep for 0.5 seconds
}
return 0;
}
Performance Optimization Tips
1. Minimize Function Calls in Inner Loops
// BAD - function called repeatedly
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
processElement(i, j); // Function call overhead
}
}
// GOOD - inline or move computation outside
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
// Inline processing
result[i][j] = i * j; // Direct computation
}
}
2. Pull Invariant Computations Out
// BAD - recomputed each iteration
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
array[i][j] = i * j * sqrt(2.0); // sqrt called 1M times
}
}
// GOOD - compute once
double factor = sqrt(2.0);
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
array[i][j] = i * j * factor;
}
}
3. Use Local Variables
// BAD - repeated array access
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
sum += matrix[i][j] * matrix[i][j]; // Multiple accesses
}
}
// GOOD - use local variable
for (int i = 0; i < 1000; i++) {
int *row = matrix[i]; // Row pointer
for (int j = 0; j < 1000; j++) {
int val = row[j]; // Single array access
sum += val * val;
}
}
Best Practices Summary
Do's and Don'ts
// DO: Use meaningful variable names
for (int row = 0; row < numRows; row++) {
for (int col = 0; col < numCols; col++) {
processCell(row, col);
}
}
// DON'T: Use single letters in complex loops
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
// Hard to understand what i and j represent
}
}
// DO: Keep loop bodies focused
for (int i = 0; i < n; i++) {
calculateRowSum(i);
}
// DON'T: Have massive loop bodies
for (int i = 0; i < n; i++) {
// 50 lines of code - hard to debug
for (int j = 0; j < m; j++) {
// Another 50 lines
}
}
// DO: Consider loop order for cache efficiency
for (int i = 0; i < rows; i++) { // Row-major
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * j;
}
}
// DO: Use break and continue sparingly but effectively
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == target) {
printf("Found at (%d,%d)\n", i, j);
goto found; // Use goto for breaking multiple loops
}
}
}
found:
Common Patterns Cheat Sheet
| Pattern | Outer Loop | Inner Loop | Use Case |
|---|---|---|---|
| Row-major | i = 0 to rows | j = 0 to cols | Matrix operations |
| Column-major | j = 0 to cols | i = 0 to rows | Column-based processing |
| Upper triangular | i = 0 to n | j = i to n | Symmetric matrices |
| Lower triangular | i = 0 to n | j = 0 to i | Triangle patterns |
| Pyramid | i = 0 to n | space, then star | Pattern printing |
| Diamond | i = 0 to 2n | space, then star | Centered patterns |
| Multiplication | i = 0 to n | j = 0 to m | Table generation |
Conclusion
Nested loops are fundamental to C programming and appear in countless applications:
Key Takeaways
- Structure: Outer loop controls major iterations, inner loop handles detailed work
- Patterns: Essential for creating visual patterns and shapes
- Matrix Operations: Required for 2D data processing
- Algorithms: Core to sorting, searching, and many algorithms
- Performance: Loop order and optimization matter significantly
When to Use Nested Loops
- Processing 2D arrays and matrices
- Creating patterns and designs
- Implementing sorting algorithms
- Working with grids and game boards
- Generating tables and reports
- Searching in 2D spaces
Mastering nested loops is essential for any C programmer, as they appear in virtually every non-trivial program. Understanding their behavior, optimization, and applications will significantly improve your coding skills.