Small C programs are useful only when each one teaches a concrete language or algorithm rule. Build, run, test boundaries, and explain the state changes instead of collecting disconnected snippets.
Every hosted C program starts at main. Include only the headers required by the functions you call, declare functions before use, return a meaningful exit status, and compile with warnings enabled. A compiler warning often identifies undefined behavior before it becomes a runtime defect.
Formatted input must match the destination type and must be checked. scanf returns the number of successful conversions; using an unchanged variable after a failed conversion is a logic error. For line-oriented input, fgets plus deliberate parsing gives better control over length and trailing text.
Choose types from the data range, check arithmetic boundaries when input is untrusted, and keep output labels clear enough that a failed test can be diagnosed.
Programs such as even/odd, maximum of three values, leap-year checks, prime tests, factorial, and digit sums teach expressions, conditions, and loop invariants. Define the accepted domain first: factorial is not defined here for negative input, and a prime test must reject values below two.
Prefer an algorithm that expresses the rule directly. A prime test needs candidate divisors only through the square root; compare divisor <= value / divisor to avoid overflow from divisor * divisor.
Array programs must carry both the storage and its element count. Searching returns a position or a clear not-found result. Sorting examples should state whether they modify the input, whether equal values remain stable, and their time and space cost.
C strings are null-terminated character arrays. Reserve space for the terminator, do not read beyond the destination, and distinguish byte length from allocated capacity.
For every program, test the smallest valid input, a typical input, repeated values, an invalid input, and the largest practical boundary. Write the expected result before running the program. Use sanitizers when available to expose out-of-bounds access, use-after-free, and undefined arithmetic.
#include <stdio.h>
int main(void) {
int a, b, c;
if (scanf("%d %d %d", &a, &b, &c) != 3) {
fputs("Expected three integers.\n", stderr);
return 1;
}
int largest = a;
if (b > largest) largest = b;
if (c > largest) largest = c;
printf("Largest: %d\n", largest);
return 0;
}
#include <stddef.h>
#include <stdio.h>
void insertion_sort(int values[], size_t count) {
for (size_t i = 1; i < count; ++i) {
int key = values[i];
size_t j = i;
while (j > 0 && values[j - 1] > key) {
values[j] = values[j - 1];
--j;
}
values[j] = key;
}
}
int main(void) {
int values[] = {7, 2, 7, -1, 4};
size_t count = sizeof values / sizeof values[0];
insertion_sort(values, count);
for (size_t i = 0; i < count; ++i) printf("%d%c", values[i], i + 1 == count ? '\n' : ' ');
}
Predict the output, type the program, compile with warnings, test boundaries, then rewrite one part of the algorithm without looking.
A snippet may assume valid input, a particular integer range, or enough array capacity. Those hidden assumptions can become undefined behavior.
Explore 500+ free tutorials across 20+ languages and frameworks.