Skip to content
Circuit

Basic C Program Examples

Examples are most useful when you predict what they will do, explain why, and change them deliberately. Running a copied program once proves very little about your understanding. Use the examples library as a set of small experiments, with one new concept and a few known test cases at each step.

Begin with output and simple input

Hello World introduces headers, main, a function call, and a newline. Change the output text, add a second line, and identify which characters belong to the source syntax versus the printed message. Keep the working program as a reference before adding input.

Add Two Numbers introduces variables, addresses, and scanf return values. Test two positives, one negative, and zero. The example limits ordinary numeric inputs before adding them. For production-style parsing of arbitrary text, use a bounded line and explicit conversion checks instead of assuming every user types a representable integer.

Conditions should cover boundaries

Even or Odd uses remainder by two. Test zero and negative numbers as well as positive ones; checking for a remainder of exactly one is not the right general test for oddness. Largest of Three starts with the first actual input as its candidate, which allows all-negative cases to work.

Write the expected answer before running each case. A useful test set targets branch boundaries: equal values, the smallest accepted value, and inputs just outside a chosen range. Repeating many ordinary positive cases can miss a single incorrect comparison that matters at the edge.

Loops need a state and a stopping rule

Factorial maintains a product and advances a counter. Fibonacci maintains the previous two terms. A multiplication table advances through an inclusive range. For each example, identify initialization, the continuation condition, and the update that guarantees progress.

Check how the program behaves when the loop runs zero times, once, and several times. The factorial example keeps its input small enough for the chosen integer type. Extending a loop bound is not enough to extend the mathematical range: arithmetic storage can overflow before the algorithm finishes.

/* Trace total after each iteration: 1, 3, 6, 10. */
int total = 0;
for (int value = 1; value <= 4; ++value) {
    total += value;
}
printf("%d\n", total);

Digit exercises expose representation choices

Reverse a Number repeatedly extracts the final digit with % 10 and removes it with integer division. Palindrome keeps an untouched copy and compares it with the reversed result. Both examples deliberately accept a bounded nonnegative range.

Reversing an integer discards leading zeroes in the result. If the task is to reverse a written identifier such as 00120 while preserving every character, use a string instead. A problem statement’s data model matters before you choose a loop. Numbers and digit strings can look alike while requiring different behavior.

Move from individual values to collections

Array Sum introduces a count-controlled traversal. Array Reverse pairs indexes from opposite ends and stops halfway. Matrix Addition uses nested loops with independent row and column bounds. Test small distinctive data so that a swapped index or skipped element is visible.

String Length demonstrates a different boundary: the first null terminator. The character array has capacity for that terminator in addition to visible text. Do not assume every byte array is a valid string or that a string’s byte length equals its number of displayed characters in every encoding.

Extract behavior into functions

Once a calculation works, move it into a function with explicit parameters and a return value. Keep prompting and printing in main at first. The Function example computes a square; the Pointer example swaps caller-owned values using copied addresses.

The Structure example groups related fields into one record. Dot and arrow access show the difference between a structure object and a pointer to it. These examples connect earlier ideas rather than replacing them: arrays still need bounds, pointers still need live objects, and functions still need clear contracts.

Use the library as a practice routine

Open an example page, read its explanation and sample input, and select Try in Circuit. It creates a new program rather than replacing an existing file. Predict the sample output, run it, then change one condition or value and explain the new result. Save useful variations under descriptive names.

Finish each exercise with one ordinary case, one boundary case, and one rejected input where relevant. If a run fails, decide whether the issue is translation, input, resource limits, or logic. The File Handling example is a useful final reminder that environment matters: its runtime file is temporary and does not survive another execution.