C Exercises
Practise what you've learned. Type the missing piece into each highlighted gap and press Check. Further down are programming challenges with editors and model solutions — copy them to compile and run locally.
Fill in the blanks
Basics
Include the header that declares printf.
#include <>
(lesson 03)
Declare the entry point of a program that takes no arguments.
int (void) {
(lesson 03)
Print an int followed by a newline.
printf("\n", count);
(lesson 11)
Print a double with two decimal places.
printf("%\n", price);
(lesson 11)
Print a size_t value.
printf("%\n", sizeof(int));
(lesson 07)
Read a double with scanf.
scanf("", &weight);
%f reads a float; %lf reads a double (lesson 15).
Get a fractional result from two ints.
double avg = () total / count;
Cast before dividing (lesson 12).
Get the remainder of a division.
int r = 17 5;
(lesson 13)
Turn on bit 3 in flags.
flags 1u << 3;
(lesson 14)
Use exact-width integer types.
#include <>
(lesson 08)
Control flow and functions
Leave a switch case.
case 'q':
running = 0;
;
Without it, execution falls through to the next case (lesson 17).
A loop whose body always runs at least once.
{
ask();
} while (!valid);
(lesson 18)
Skip to the next iteration of a loop.
if (value < 0) ;
(lesson 20)
Declare a function before it's defined (a prototype).
int square(int n)
A prototype ends with a semicolon instead of a body (lesson 21).
Keep a local variable's value between calls.
int calls = 0;
(lesson 23)
Arrays and strings
Number of elements in an array.
size_t n = sizeof values / ;
(lesson 26)
The character that ends every C string.
buffer[len] = '';
(lesson 28)
Length of a string, not counting the terminator.
size_t len = (name);
(lesson 28)
Compare two strings by their contents.
if ((a, b) == 0) puts("same");
== would compare addresses (lesson 29).
Read a whole line safely.
(line, sizeof line, stdin);
(lesson 15)
Format text into an array without overflowing it.
(label, sizeof label, "Order #%d", id);
(lesson 29)
Test whether a character is a digit.
if (((unsigned char) c)) digits++;
From ctype.h (lesson 30).
Pointers and memory
Store the address of score in a pointer.
int *p = score;
(lesson 31)
Change the value a pointer points to.
p = 100;
Dereferencing (lesson 31).
A pointer that points to nothing.
int *p = ;
(lesson 31)
Promise that a function won't modify the string it receives.
size_t count_spaces( char *s);
(lesson 35)
Allocate an array of n doubles on the heap.
double *data = (n * sizeof *data);
Then check for NULL (lesson 36).
Release memory you allocated.
(data);
(lesson 36)
Allocate memory that starts out zeroed.
int *counts = (26, sizeof *counts);
(lesson 36)
Grow an allocation (using a temporary pointer).
int *grown = (items, new_cap * sizeof *items);
(lesson 37)
Structures and files
Access a member through a pointer to a struct.
pscore = 90;
Same as (*p).score (lesson 41).
Give a struct type a shorter name.
struct { double x, y; } Point;
(lesson 44)
Sort an array with the standard library.
(scores, n, sizeof scores[0], compare_ints);
(lesson 46)
Open a file for appending.
FILE *log = fopen("app.log", "");
"w" would erase it first (lesson 47).
Close a file when you're done.
(log);
(lesson 47)
Print an error message with the system's reason.
("settings.ini");
(lesson 50)
Prevent a header from being included twice.
# STATS_H #define STATS_H /* ... */ #endif
An include guard (lesson 51).
Make a function private to its source file.
int helper(int x);
(lesson 52)
Programming challenges
1. FizzBuzz
Print the numbers 1 to 15, but "Fizz" for multiples of 3, "Buzz" for multiples of 5 and "FizzBuzz" for both.
Show a model solution
#include <stdio.h> int main(void) { for (int i = 1; i <= 15; i++) { if (i % 15 == 0) printf("FizzBuzz "); else if (i % 3 == 0) printf("Fizz "); else if (i % 5 == 0) printf("Buzz "); else printf("%d ", i); } printf("\n"); return 0; }
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz
2. Letter frequencies
Count how often each letter appears in a sentence, ignoring case, and print the letters that appear at least twice.
Show a model solution
#include <stdio.h> #include <ctype.h> int main(void) { const char *text = "The quick brown fox jumps over the lazy dog"; int counts[26] = { 0 }; for (const char *p = text; *p; p++) { unsigned char c = *p; if (isalpha(c)) counts[tolower(c) - 'a']++; } for (int i = 0; i < 26; i++) { if (counts[i] >= 2) printf("%c: %d\n", 'a' + i, counts[i]); } return 0; }
e: 3 h: 2 o: 4 r: 2 t: 2 u: 2
3. Reverse the words
Write a function that reverses the order of the words in a string in place: "one two three" becomes "three two one". Hint: reverse the whole string, then reverse each word.
Show a model solution
#include <stdio.h> #include <string.h> static void reverse_range(char *start, char *end) { // end is exclusive while (start < --end) { char t = *start; *start++ = *end; *end = t; } } void reverse_words(char *s) { size_t len = strlen(s); reverse_range(s, s + len); char *word = s; for (char *p = s; ; p++) { if (*p == ' ' || *p == '\0') { reverse_range(word, p); if (*p == '\0') break; word = p + 1; } } } int main(void) { char sentence[] = "pointers are not that scary"; reverse_words(sentence); printf("%s\n", sentence); return 0; }
scary that not are pointers
4. A dynamic stack
Implement a stack of int that grows with realloc, with push, pop and free functions. Use it to check whether brackets in a string are balanced.
Show a model solution
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef struct { int *items; size_t count, capacity; } Stack; static bool push(Stack *s, int v) { if (s->count == s->capacity) { size_t cap = s->capacity ? s->capacity * 2 : 8; int *grown = realloc(s->items, cap * sizeof *grown); if (grown == NULL) return false; s->items = grown; s->capacity = cap; } s->items[s->count++] = v; return true; } static bool pop(Stack *s, int *out) { if (s->count == 0) return false; *out = s->items[--s->count]; return true; } static void stack_free(Stack *s) { free(s->items); *s = (Stack) { 0 }; } static bool balanced(const char *text) { Stack s = { 0 }; bool ok = true; for (const char *p = text; *p && ok; p++) { int open; switch (*p) { case '(': case '[': case '{': ok = push(&s, *p); break; case ')': ok = pop(&s, &open) && open == '('; break; case ']': ok = pop(&s, &open) && open == '['; break; case '}': ok = pop(&s, &open) && open == '{'; break; } } ok = ok && s.count == 0; stack_free(&s); return ok; } int main(void) { const char *tests[] = { "{[()()]}", "([)]", "((", "f(a[1], {b})" }; for (int i = 0; i < 4; i++) { printf("%-14s %s\n", tests[i], balanced(tests[i]) ? "balanced" : "not balanced"); } return 0; }
{[()()]} balanced
([)] not balanced
(( not balanced
f(a[1], {b}) balanced5. Word count from a file
Read a text file and print its number of lines, words and characters, like the Unix wc command.
Buy milk Call the plumber about the leak Finish the C course
Show a model solution
#include <stdio.h> #include <ctype.h> int main(void) { FILE *f = fopen("notes.txt", "r"); if (f == NULL) { perror("notes.txt"); return 1; } long lines = 0, words = 0, chars = 0; int in_word = 0, c; while ((c = fgetc(f)) != EOF) { chars++; if (c == '\n') lines++; if (isspace(c)) { in_word = 0; } else if (!in_word) { in_word = 1; words++; } } fclose(f); printf("%ld lines, %ld words, %ld characters\n", lines, words, chars); return 0; }
3 lines, 12 words, 61 characters