loops in C exercises for while do while solutions cheat sheet Fedora

Loops in C exercises — master for, while and do…while

Loops in C exercises are where for, while and do...while stop feeling like abstract concepts and become tools you reach for naturally. You’ve seen the theory and built three complete programs. Now it’s time to solve challenges on your own in Fedora — including Rock Paper Scissors, a number base converter, prime numbers and a final challenge that combines everything.

Set up your workspace:

cd ~/GCID/IC2/Labs
mkdir exercises_loops
cd exercises_loops

As always: try to solve it in gedit, compile with gcc, use the hint if stuck for more than 10 minutes, and compare with the commented solution.


Loops in C exercises — Basic Level

Exercise 1 — Rock Paper Scissors

Write a C program that lets the player play Rock Paper Scissors against the computer. The computer’s choice is random. Play until the player chooses to quit.

Rules: rock beats scissors, scissors beats paper, paper beats rock.

=== ROCK PAPER SCISSORS ===

1. Rock
2. Paper
3. Scissors
0. Quit
Your choice: 1

You:      Rock
Computer: Scissors
Result:   You win!

--- New round ---
1. Rock
2. Paper
3. Scissors
0. Quit
Your choice: 0

=== Final Score ===
Wins:   2
Losses: 1
Draws:  1
Total:  4
Win rate: 50.0%

💡 Hints:

  • Use srand(time(NULL)) and computer = (rand() % 3) + 1 for random choice (1=Rock, 2=Paper, 3=Scissors)
  • Use do...while (choice != 0) for the game loop — must show menu at least once
  • Win condition: (player==1 && computer==3) || (player==2 && computer==1) || (player==3 && computer==2)
  • Use a switch for displaying the choice name and another for the result message
  • Track wins, losses, draws with three counters

Exercise 2 — Number base converter

Write a C program that reads a positive integer and converts it to binary manually — without using %b (which doesn’t exist in C) or printf format specifiers. Convert using repeated division by 2.

Also convert to octal and hexadecimal using printf specifiers, and show the digit-by-digit breakdown.

=== NUMBER BASE CONVERTER ===

Number (positive integer): 42

--- Conversions ---
Decimal:     42
Binary:      101010
Octal:       52
Hexadecimal: 2a  (uppercase: 2A)

--- Binary conversion steps ---
42 / 2 = 21  remainder 0
21 / 2 = 10  remainder 1
10 / 2 =  5  remainder 0
 5 / 2 =  2  remainder 1
 2 / 2 =  1  remainder 0
 1 / 2 =  0  remainder 1
Read remainders bottom to top: 101010

💡 Hints:

  • Store binary digits in an array: int bits[32]
  • while (n > 0) { bits[count++] = n % 2; n /= 2; }
  • Print the array in reverse: for (int i = count-1; i >= 0; i--)
  • Show the steps with a second loop over the original number
  • Octal: %o, hexadecimal lowercase: %x, uppercase: %X

Loops in C exercises — Intermediate Level

Exercise 3 — Prime number sieve

Write a C program that finds all prime numbers up to N using a nested loop approach. Show the primes, their count, and identify twin primes (pairs that differ by 2).

=== PRIME NUMBER FINDER ===

Find primes up to N: 50

Primes up to 50:
 2  3  5  7 11 13 17 19 23 29 31 37 41 43 47

--- Statistics ---
Count:           15
Largest prime:   47
Sum of primes:  328
Density:        30.0% (15 out of 50 numbers)

--- Twin primes (differ by 2) ---
(3,5) (5,7) (11,13) (17,19) (29,31) (41,43)
Count: 6 twin prime pairs

💡 Hints:

  • Outer for from 2 to N — each candidate
  • Inner for from 2 to sqrt(candidate) — check divisibility: i * i <= candidate
  • Use is_prime = 1 flag, set to 0 if divisor found, break immediately
  • Store primes in array int primes[1000] for twin prime detection
  • Twin prime check: for (int i = 0; i < count-1; i++) if (primes[i+1] - primes[i] == 2)
  • sqrt() requires #include <math.h> and -lm flag: gcc ... -Wall -lm

Loops in C exercises — Final Challenge

Exercise 4 — Student grade book

Write a C program that manages grades for a group of students. It reads names and grades, calculates statistics and shows a ranked list.

=== GRADE BOOK ===

How many students? 4

Student 1 name: Alice
Grade: 8.5

Student 2 name: Bob
Grade: 6.0

Student 3 name: Carlos
Grade: 9.2

Student 4 name: Diana
Grade: 4.5

=== Results ===

--- Individual results ---
Alice  : 8.50  B  Merit
Bob    : 6.00  C  Passed
Carlos : 9.20  A  Outstanding
Diana  : 4.50  F  Failed

--- Class statistics ---
Average:  7.06
Highest:  9.20 (Carlos)
Lowest:   4.50 (Diana)
Passed:   3/4 (75.0%)
Failed:   1/4 (25.0%)

--- Ranking (highest to lowest) ---
1st  Carlos  9.20  A
2nd  Alice   8.50  B
3rd  Bob     6.00  C
4th  Diana   4.50  F

💡 Hints:

  • Use parallel arrays: char names[30][50], double grades[30]
  • First for loop: read names and grades with scanf("%s", names[i]) and scanf("%lf", &grades[i])
  • Second for loop: calculate sum, find max/min and their index, count pass/fail
  • Sorting: bubble sort with nested for — swap both grades[j] and names[j] together when out of order
  • Letter grade: use a function-like pattern — check ranges with if/else if for each student
  • For ranking, sort a copy of the arrays or sort both arrays together

Commented solutions

Solution Exercise 1

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    int player, computer;
    int wins = 0, losses = 0, draws = 0;
    int total;

    srand(time(NULL));

    printf("=== ROCK PAPER SCISSORS ===\n");

    do {
        printf("\n1. Rock\n2. Paper\n3. Scissors\n0. Quit\n");
        printf("Your choice: ");
        scanf("%d", &player);

        if (player == 0) break;

        if (player < 1 || player > 3) {
            printf("Invalid option\n");
            continue;
        }

        computer = (rand() % 3) + 1;

        /* Show choices */
        printf("\nYou:      ");
        switch (player) {
            case 1: printf("Rock\n"); break;
            case 2: printf("Paper\n"); break;
            case 3: printf("Scissors\n"); break;
        }

        printf("Computer: ");
        switch (computer) {
            case 1: printf("Rock\n"); break;
            case 2: printf("Paper\n"); break;
            case 3: printf("Scissors\n"); break;
        }

        /* Determine result */
        printf("Result:   ");
        if (player == computer) {
            printf("Draw!\n");
            draws++;
        } else if ((player == 1 && computer == 3) ||
                   (player == 2 && computer == 1) ||
                   (player == 3 && computer == 2)) {
            printf("You win!\n");
            wins++;
        } else {
            printf("Computer wins!\n");
            losses++;
        }

        printf("\n--- New round ---");

    } while (player != 0);

    total = wins + losses + draws;
    printf("\n=== Final Score ===\n");
    printf("Wins:   %d\n", wins);
    printf("Losses: %d\n", losses);
    printf("Draws:  %d\n", draws);
    printf("Total:  %d\n", total);
    if (total > 0)
        printf("Win rate: %.1f%%\n", (double)wins / total * 100);

    return 0;
}

Solution Exercise 2

#include <stdio.h>

int main() {
    int n, original;
    int bits[32];
    int count = 0;

    printf("=== NUMBER BASE CONVERTER ===\n\n");
    printf("Number (positive integer): ");
    scanf("%d", &n);

    if (n <= 0) {
        printf("Error: must be positive\n");
        return 1;
    }

    original = n;

    /* Build binary digit array */
    int temp = n;
    while (temp > 0) {
        bits[count++] = temp % 2;
        temp /= 2;
    }

    printf("\n--- Conversions ---\n");
    printf("Decimal:     %d\n", n);

    printf("Binary:      ");
    for (int i = count - 1; i >= 0; i--)
        printf("%d", bits[i]);
    printf("\n");

    printf("Octal:       %o\n", n);
    printf("Hexadecimal: %x  (uppercase: %X)\n", n, n);

    /* Show conversion steps */
    printf("\n--- Binary conversion steps ---\n");
    temp = original;
    while (temp > 0) {
        printf("%2d / 2 = %2d  remainder %d\n",
               temp, temp / 2, temp % 2);
        temp /= 2;
    }
    printf("Read remainders bottom to top: ");
    for (int i = count - 1; i >= 0; i--)
        printf("%d", bits[i]);
    printf("\n");

    return 0;
}

Solution Exercise 3

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

int main() {
    int n;
    int primes[1000];
    int count = 0;

    printf("=== PRIME NUMBER FINDER ===\n\n");
    printf("Find primes up to N: ");
    scanf("%d", &n);

    printf("\nPrimes up to %d:\n", n);

    for (int candidate = 2; candidate <= n; candidate++) {
        int is_prime = 1;
        int limit = (int)sqrt((double)candidate);

        for (int i = 2; i <= limit; i++) {
            if (candidate % i == 0) {
                is_prime = 0;
                break;
            }
        }

        if (is_prime) {
            printf("%3d", candidate);
            primes[count++] = candidate;
        }
    }
    printf("\n");

    /* Statistics */
    long sum = 0;
    for (int i = 0; i < count; i++)
        sum += primes[i];

    printf("\n--- Statistics ---\n");
    printf("Count:       %d\n", count);
    printf("Largest:     %d\n", count > 0 ? primes[count-1] : 0);
    printf("Sum:         %ld\n", sum);
    printf("Density:     %.1f%% (%d out of %d numbers)\n",
           (double)count / n * 100, count, n);

    /* Twin primes */
    int twin_count = 0;
    printf("\n--- Twin primes (differ by 2) ---\n");
    for (int i = 0; i < count - 1; i++) {
        if (primes[i+1] - primes[i] == 2) {
            printf("(%d,%d) ", primes[i], primes[i+1]);
            twin_count++;
        }
    }
    printf("\nCount: %d twin prime pairs\n", twin_count);

    return 0;
}

Compile with -lm for the math library:

gcc primes.c -o primes -Wall -lm
./primes

Solution Exercise 4

#include <stdio.h>

#define MAX 30

int main() {
    int n;
    char names[MAX][50];
    double grades[MAX];

    printf("=== GRADE BOOK ===\n\n");
    printf("How many students? ");
    scanf("%d", &n);

    if (n <= 0 || n > MAX) {
        printf("Error: between 1 and %d students\n", MAX);
        return 1;
    }

    /* Read students */
    for (int i = 0; i < n; i++) {
        printf("\nStudent %d name: ", i + 1);
        scanf("%s", names[i]);
        printf("Grade: ");
        scanf("%lf", &grades[i]);
    }

    /* Calculate statistics */
    double sum = 0;
    double max_grade = grades[0], min_grade = grades[0];
    int max_idx = 0, min_idx = 0;
    int passed = 0;

    for (int i = 0; i < n; i++) {
        sum += grades[i];
        if (grades[i] > max_grade) { max_grade = grades[i]; max_idx = i; }
        if (grades[i] < min_grade) { min_grade = grades[i]; min_idx = i; }
        if (grades[i] >= 5.0) passed++;
    }

    /* Letter grade function inline */
    char get_letter(double g);  /* forward declaration */

    /* Display results */
    printf("\n=== Results ===\n\n--- Individual results ---\n");
    for (int i = 0; i < n; i++) {
        char letter;
        const char *class;
        if (grades[i] >= 9.0)      { letter = 'A'; class = "Outstanding"; }
        else if (grades[i] >= 7.0) { letter = 'B'; class = "Merit"; }
        else if (grades[i] >= 5.0) { letter = 'C'; class = "Passed"; }
        else                       { letter = 'F'; class = "Failed"; }
        printf("%-8s: %.2f  %c  %s\n", names[i], grades[i], letter, class);
    }

    printf("\n--- Class statistics ---\n");
    printf("Average:  %.2f\n", sum / n);
    printf("Highest:  %.2f (%s)\n", max_grade, names[max_idx]);
    printf("Lowest:   %.2f (%s)\n", min_grade, names[min_idx]);
    printf("Passed:   %d/%d (%.1f%%)\n", passed, n, (double)passed/n*100);
    printf("Failed:   %d/%d (%.1f%%)\n", n-passed, n, (double)(n-passed)/n*100);

    /* Sort copies for ranking (bubble sort) */
    char sorted_names[MAX][50];
    double sorted_grades[MAX];
    for (int i = 0; i < n; i++) {
        sorted_grades[i] = grades[i];
        for (int c = 0; c < 50; c++)
            sorted_names[i] = names[i];
    }

    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1 - i; j++) {
            if (sorted_grades[j] < sorted_grades[j+1]) {
                double tmp_g = sorted_grades[j];
                sorted_grades[j] = sorted_grades[j+1];
                sorted_grades[j+1] = tmp_g;
                char tmp_n[50];
                for (int c = 0; c < 50; c++) tmp_n = sorted_names[j];
                for (int c = 0; c < 50; c++) sorted_names[j] = sorted_names[j+1];
                for (int c = 0; c < 50; c++) sorted_names[j+1] = tmp_n;
            }
        }
    }

    const char *ranks[] = {"1st","2nd","3rd","4th","5th",
                           "6th","7th","8th","9th","10th"};
    printf("\n--- Ranking (highest to lowest) ---\n");
    for (int i = 0; i < n; i++) {
        char letter;
        if (sorted_grades[i] >= 9.0)      letter = 'A';
        else if (sorted_grades[i] >= 7.0) letter = 'B';
        else if (sorted_grades[i] >= 5.0) letter = 'C';
        else                              letter = 'F';
        printf("%-4s %-8s %.2f  %c\n",
               (i < 10) ? ranks[i] : "...",
               sorted_names[i], sorted_grades[i], letter);
    }

    return 0;
}

Visualise with Python Tutor

Select C from the dropdown and paste in pythontutor.com:

#include <stdio.h>
int main() {
    int nums[5] = {64, 25, 12, 22, 11};
    int n = 5;

    /* Bubble sort — nested for loops */
    for (int i = 0; i < n-1; i++) {
        for (int j = 0; j < n-1-i; j++) {
            if (nums[j] > nums[j+1]) {
                int temp = nums[j];
                nums[j] = nums[j+1];
                nums[j+1] = temp;
            }
        }
    }

    for (int i = 0; i < n; i++)
        printf("%d ", nums[i]);
    return 0;
}

Step through the bubble sort and watch how the nested loops work. The outer loop runs 4 times (n-1). On each outer iteration the inner loop places the largest remaining unsorted element at the end of the unsorted portion — like a bubble rising to the surface. After the first outer pass, 64 is in position 4. After the second, 25 is in position 3. Watch how n-1-i reduces the inner loop’s range on each outer iteration — no need to re-check elements already sorted at the end.


Cheat sheet — Loops in C

/* ============================================
   CHEAT SHEET — Loops in C
   Sergio Learns · sergiolearns.com
   ============================================ */

/* FOR — known iterations */
for (int i = 0; i < n; i++) { }      /* 0 to n-1 */
for (int i = 1; i <= n; i++) { }     /* 1 to n */
for (int i = n; i > 0; i--) { }      /* n down to 1 */
for (int i = 0; i < n; i += 2) { }   /* step 2 */
for (int i = 0; i < n; i += step) { } /* custom step */

/* RANGE EQUIVALENTS (Python → C) */
/* range(n)      → for (int i = 0; i < n; i++) */
/* range(a,b)    → for (int i = a; i < b; i++) */
/* range(a,b,s)  → for (int i = a; i < b; i += s) */
/* range(n,0,-1) → for (int i = n; i > 0; i--) */

/* INCREMENT OPERATORS */
i++   /* i = i + 1 (post) */
i--   /* i = i - 1 (post) */
i += n    i -= n    i *= n    i /= n    i %= n

/* WHILE — condition-based */
while (condition) {
    /* code */
    /* ALWAYS update condition inside */
}
/* May never execute if condition starts false */

/* DO...WHILE — always runs at least once */
do {
    /* code */
} while (condition);    /* semicolon required */

/* WHEN TO USE EACH */
/* for        → know how many: counters, arrays, series */
/* while      → don't know: search, sentinel, games */
/* do...while → need at least one: menus, validation */

/* BREAK AND CONTINUE */
break;      /* exit loop immediately */
continue;   /* skip to next iteration */

/* NESTED LOOPS */
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        /* use different variable names: i, j, k */
    }
}
/* break only exits innermost loop */
/* use flag to exit multiple levels: */
int found = 0;
for (int i = 0; i < n && !found; i++) {
    for (int j = 0; j < m && !found; j++) {
        if (condition) found = 1;
    }
}

/* ACCUMULATOR PATTERN */
double sum = 0;                    /* 1. init BEFORE */
for (int i = 0; i < n; i++) {
    sum += values[i];              /* 2. update INSIDE */
}
double avg = sum / (double)n;      /* 3. use AFTER — (double) avoids int division */

/* RANDOM NUMBERS */
#include <stdlib.h>
#include <time.h>
srand(time(NULL));                /* seed once at start of main */
int r = rand() % n;               /* 0 to n-1 */
int r = (rand() % n) + 1;        /* 1 to n */

/* BUBBLE SORT PATTERN */
for (int i = 0; i < n-1; i++) {
    for (int j = 0; j < n-1-i; j++) {
        if (arr[j] > arr[j+1]) {
            int tmp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = tmp;
        }
    }
}

/* PRIME CHECK PATTERN */
int is_prime = 1;
for (int i = 2; i * i <= n; i++) {
    if (n % i == 0) { is_prime = 0; break; }
}
/* requires #include <math.h> if using sqrt() */
/* compile with: gcc ... -Wall -lm */

/* BINARY CONVERSION PATTERN */
int bits[32], count = 0;
while (n > 0) {
    bits[count++] = n % 2;
    n /= 2;
}
for (int i = count-1; i >= 0; i--)
    printf("%d", bits[i]);

/* COMMON ERRORS */
/* 1. Infinite loop — forgot to update condition */
/* 2. Off-by-one: use i < n not i <= n for 0-based */
/* 3. Integer division in average: sum/(double)n */
/* 4. Missing semicolon after do...while condition */
/* 5. Ctrl+C to stop infinite loop in terminal */

/* COMPILE AND RUN */
/* gcc exercises.c -o exercises -Wall */
/* gcc primes.c -o primes -Wall -lm  (with math) */
/* ./exercises                         */

Similar Posts

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *