basics · beginner · ~20 min
Modular arithmetic, character classification, and the negative-modulo trap.
Shift every letter of a string forward in the alphabet by a fixed amount, wrapping around at the ends — the classic Caesar cipher.
Implement void caesar_shift(char *s, int k) that rotates each ASCII letter in s by k positions, wrapping within its own case (A..Z stays uppercase, a..z stays lowercase). Non-letter characters are left exactly as they are. The string is modified in place.
A NUL-terminated, writable string s, and a shift amount int k. k may be positive, negative, or larger than 26 — normalise it modulo 26.
No return value. s is rewritten in place with each letter shifted.
caesar_shift("abc", 1) -> "bcd"
caesar_shift("xyz", 3) -> "abc" (wraps past 'z')
caesar_shift("Hello, X!", 1) -> "Ifmmp, Y!"
caesar_shift("abc", -1) -> "zab" (negative wraps)
caesar_shift("abc", 27) -> "bcd" (27 mod 26 == 1)
k == 0 leave the string unchanged.k must wrap correctly — normalise with ((k % 26) + 26) % 26.The Caesar cipher is the Hello World of cryptography — never use it for real secrets, but implementing it teaches modular arithmetic over a small alphabet and is great practice with isupper/islower. (Real applications use vetted libraries like libsodium.)
A NUL-terminated writable string s and a shift amount int k (any value).
No return value; s is shifted in place.
ASCII only, no allocations, single pass. Normalise k modulo 26 (handle negatives).
void caesar_shift(char *s, int k) { /* TODO */ }
Forgetting that (-1) % 26 == -1 in C — the result must be normalised by adding 26 before the final %. Treating uppercase and lowercase with one branch (causes case-swapping bugs).
Empty string; k == 0; k negative; k > 26.
O(strlen(s)).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.