These programs turn individual C concepts into complete console exercises. Trace the input, identify the loop or function that performs the work, predict the output, and then test an edge case before comparing your result with the solution.
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
#include <stdio.h>
int main() {
int a, b, sum;
printf("Enter two integers: ");
scanf("%d %d", &a, &b);
sum = a + b;
printf("Sum of %d and %d = %d\n", a, b, sum);
return 0;
}
#include <stdio.h>
int main() {
int n;
long long fact = 1;
printf("Enter a positive integer: ");
scanf("%d", &n);
if (n < 0) {
printf("Factorial not defined for negative numbers.\n");
} else {
for (int i = 1; i <= n; i++) fact *= i;
printf("%d! = %lld\n", n, fact);
}
return 0;
}
/* Output: 5! = 120 */
#include <stdio.h>
long long factorial(int n) {
if (n == 0 || n == 1) return 1;
return n * factorial(n - 1);
}
int main() {
int n;
printf("Enter a positive integer: ");
scanf("%d", &n);
printf("%d! = %lld\n", n, factorial(n));
return 0;
}
#include <stdio.h>
int main() {
int n;
printf("Enter number of terms: ");
scanf("%d", &n);
long long a = 0, b = 1, c;
printf("Fibonacci series: ");
for (int i = 0; i < n; i++) {
printf("%lld ", a);
c = a + b;
a = b;
b = c;
}
printf("\n");
return 0;
}
/* Output (n=8): 0 1 1 2 3 5 8 13 */
#include <stdio.h>
#include <math.h>
int isPrime(int n) {
if (n < 2) return 0;
if (n == 2) return 1;
if (n % 2 == 0) return 0;
for (int i = 3; i <= (int)sqrt(n); i += 2) {
if (n % i == 0) return 0;
}
return 1;
}
int main() {
int n;
printf("Enter a number: ");
scanf("%d", &n);
printf("%d is %s\n", n, isPrime(n) ? "prime" : "not prime");
// Print all primes up to 50
printf("Primes up to 50: ");
for (int i = 2; i <= 50; i++) {
if (isPrime(i)) printf("%d ", i);
}
printf("\n");
return 0;
}
/* Compile: gcc prime.c -o prime -lm */
#include <stdio.h>
int main() {
int n, original, reversed = 0, digit;
printf("Enter a number: ");
scanf("%d", &n);
original = n;
while (n != 0) {
digit = n % 10;
reversed = reversed * 10 + digit;
n /= 10;
}
if (original == reversed)
printf("%d is a palindrome\n", original);
else
printf("%d is not a palindrome\n", original);
return 0;
}
/* 121 -> palindrome, 123 -> not palindrome */
#include <stdio.h>
#include <string.h>
void reverseString(char str[]) {
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
char temp = str[i];
str[i] = str[len - 1 - i];
str[len - 1 - i] = temp;
}
}
int main() {
char str[100];
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
str[strcspn(str, "\n")] = '\0'; // remove newline
printf("Original: %s\n", str);
reverseString(str);
printf("Reversed: %s\n", str);
return 0;
}
/* "Hello" -> "olleH" */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int isPalindrome(char str[]) {
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
if (tolower(str[i]) != tolower(str[len - 1 - i])) return 0;
}
return 1;
}
int main() {
char words[][20] = {"racecar", "hello", "madam", "level", "world"};
for (int i = 0; i < 5; i++) {
printf("%-10s -> %s\n", words[i],
isPalindrome(words[i]) ? "palindrome" : "not palindrome");
}
return 0;
}
/* racecar -> palindrome, hello -> not palindrome */
#include <stdio.h>
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int swapped = 0;
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = 1;
}
}
if (!swapped) break; // already sorted
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Before: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
bubbleSort(arr, n);
printf("\nAfter: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n");
return 0;
}
/* After: 11 12 22 25 34 64 90 */
#include <stdio.h>
int binarySearch(int arr[], int n, int target) {
int low = 0, high = n - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == target) return mid;
else if (arr[mid] < target) low = mid + 1;
else high = mid - 1;
}
return -1; // not found
}
int main() {
int arr[] = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 23;
int idx = binarySearch(arr, n, target);
if (idx != -1)
printf("%d found at index %d\n", target, idx);
else
printf("%d not found\n", target);
return 0;
}
/* 23 found at index 5 */
#include <stdio.h>
int main() {
int a = 5, b = 10;
printf("Original: a=%d, b=%d\n", a, b);
// Method 1: Using temp variable
int temp = a; a = b; b = temp;
printf("After temp swap: a=%d, b=%d\n", a, b);
// Method 2: Using XOR (no temp variable)
a = 5; b = 10;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("After XOR swap: a=%d, b=%d\n", a, b);
// Method 3: Using pointers
void swapPtr(int *x, int *y);
a = 5; b = 10;
swapPtr(&a, &b);
printf("After ptr swap: a=%d, b=%d\n", a, b);
return 0;
}
void swapPtr(int *x, int *y) {
int t = *x; *x = *y; *y = t;
}
#include <stdio.h>
int main() {
int arr[] = {34, 78, 12, 56, 90, 23, 45};
int n = sizeof(arr) / sizeof(arr[0]);
int largest = arr[0], smallest = arr[0];
int largestIdx = 0, smallestIdx = 0;
for (int i = 1; i < n; i++) {
if (arr[i] > largest) { largest = arr[i]; largestIdx = i; }
if (arr[i] < smallest) { smallest = arr[i]; smallestIdx = i; }
}
printf("Array: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\nLargest: %d (index %d)\n", largest, largestIdx);
printf("Smallest: %d (index %d)\n", smallest, smallestIdx);
return 0;
}
/* Largest: 90 (index 4), Smallest: 12 (index 2) */
#include <stdio.h>
#define N 3
int main() {
int a[N][N] = {{1,2,3},{4,5,6},{7,8,9}};
int b[N][N] = {{9,8,7},{6,5,4},{3,2,1}};
int c[N][N] = {0};
// Matrix multiplication: c[i][j] = sum of a[i][k] * b[k][j]
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < N; k++)
c[i][j] += a[i][k] * b[k][j];
printf("Result of A x B:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) printf("%5d", c[i][j]);
printf("\n");
}
return 0;
}
/*
30 24 18
84 69 54
138 114 90
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int isVowel(char c) {
c = tolower(c);
return c=='a' || c=='e' || c=='i' || c=='o' || c=='u';
}
int main() {
char str[200];
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
int vowels = 0, consonants = 0, spaces = 0, digits = 0;
for (int i = 0; str[i] != '\0'; i++) {
if (isalpha(str[i])) {
if (isVowel(str[i])) vowels++;
else consonants++;
} else if (isspace(str[i])) spaces++;
else if (isdigit(str[i])) digits++;
}
printf("Vowels: %d\n", vowels);
printf("Consonants: %d\n", consonants);
printf("Spaces: %d\n", spaces);
printf("Digits: %d\n", digits);
return 0;
}
/* "Hello World 123" -> Vowels:3, Consonants:7, Spaces:2, Digits:3 */
Before writing a small C program, state the accepted input domain, expected output format, and behavior for invalid input. This prevents an exercise from silently assuming positive numbers, non-empty arrays, or successful conversion. Keep input parsing at the boundary and pass validated values into a function that implements the calculation.
Compile with warnings enabled and treat the first warning as a defect to understand. A program that prints the expected value for one sample can still contain undefined behavior, overflow, or an unchecked read.
For numeric programs, test zero, one, negative values when allowed, and the largest supported input. For arrays and strings, test empty, one-element, duplicate, already ordered, and maximum-length cases. Predict the result before running the program so a surprising output becomes evidence instead of noise.
When a program loops or recurses, identify the measure that changes on every iteration. A boundary test should confirm both termination and the final state, not merely that the process did not crash.
Put reusable logic in a function whose arguments and return value can be tested without terminal input. Keep main responsible for reading, validating, calling the function, printing, and choosing an exit status. This separation makes the same calculation usable from a test, another program, or a future user interface.
Verify each program with a small table of input, expected output, actual output, and exit status. Add one invalid case and one boundary case before considering the exercise complete.
scanf returns the number of successful conversions. If input does not match the requested type, the target variable may remain unchanged and the invalid characters can stay in the input stream.
Test an empty logical range, one element, duplicates, negative values, already sorted data, reverse order, and a missing search target. Also test the maximum supported input count.
Undefined behavior often produces the expected output during one run. Options such as -Wall, -Wextra, and relevant sanitizers catch type mismatches, uninitialized values, invalid formats, out-of-bounds access, and lifetime bugs that printed output may not reveal. A clean sample result is weaker evidence than warnings plus edge-case tests.
Explore 500+ free tutorials across 20+ languages and frameworks.