Step 2: The C version
C has no built-in dictionary or string type, so you build the pieces: a fixed-size array of struct Entry (word and count), a loop that scans for an existing word (strcmp) or adds a new one, a loop that splits the text by hand with isalpha, and qsort with your own comparison function. It is more code, but nothing is hidden: you see exactly how counting works.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_WORDS 100
#define MAX_LEN 32
struct Entry {
char word[MAX_LEN];
int count;
};
static struct Entry entries[MAX_WORDS];
static int used = 0;
void add_word(const char *word) {
for (int i = 0; i < used; i++) {
if (strcmp(entries[i].word, word) == 0) {
entries[i].count++;
return;
}
}
if (used < MAX_WORDS) {
strncpy(entries[used].word, word, MAX_LEN - 1);
entries[used].count = 1;
used++;
}
}
int by_count_then_word(const void *a, const void *b) {
const struct Entry *x = a, *y = b;
if (x->count != y->count) return y->count - x->count;
return strcmp(x->word, y->word);
}
int main(void) {
char text[] = "The quick brown fox jumps over the lazy dog. The end!";
char word[MAX_LEN];
int len = 0;
for (char *p = text; ; p++) {
if (isalpha((unsigned char)*p) && len < MAX_LEN - 1) {
word[len++] = tolower((unsigned char)*p);
} else {
if (len > 0) {
word[len] = '\0';
add_word(word);
len = 0;
}
if (*p == '\0') break;
}
}
qsort(entries, used, sizeof(struct Entry), by_count_then_word);
for (int i = 0; i < used; i++) {
printf("%-6s %d\n", entries[i].word, entries[i].count);
}
return 0;
}the 3 brown 1 dog 1 end 1 fox 1 jumps 1 lazy 1 over 1 quick 1
What C asks of you: you choose the limits (MAX_WORDS, MAX_LEN) and must make sure you never write past them, because C will not stop you. In exchange you get a tiny, very fast program that uses almost no memory.
What does C use instead of a built-in dictionary here?
Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.
Tip: use the left and right arrow keys to move between lessons.