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.
Table of Contents
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))andcomputer = (rand() % 3) + 1for 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
switchfor 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
forfrom 2 to N — each candidate - Inner
forfrom 2 tosqrt(candidate)— check divisibility:i * i <= candidate - Use
is_prime = 1flag, set to 0 if divisor found,breakimmediately - 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-lmflag: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
forloop: read names and grades withscanf("%s", names[i])andscanf("%lf", &grades[i]) - Second
forloop: calculate sum, find max/min and their index, count pass/fail - Sorting: bubble sort with nested
for— swap bothgrades[j]andnames[j]together when out of order - Letter grade: use a function-like pattern — check ranges with
if/else iffor 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 */

One Comment