C programming
string generation
algorithm
coding tutorial
recursion

Generate all strings under length N in C

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Generating all strings of length up to N is a straightforward recursive backtracking problem once you choose the alphabet and the output order. The main decisions are whether to include the empty string, how to store the current prefix, and whether to print results immediately or pass them to a callback for later use.

Start with the Problem Shape

Suppose your alphabet is {'a', 'b', 'c'} and the maximum length is 3. The generated strings are:

  • length 1: a, b, c
  • length 2: aa, ab, ac, ba, and so on
  • length 3: aaa, aab, aac, and so on

The total number of non-empty strings is:

k^1 + k^2 + ... + k^N

where k is the alphabet size.

That growth becomes large quickly, so generation is practical only for moderate values of N.

Use One Buffer and Backtracking

A clean C solution keeps one writable buffer and fills it character by character. When a prefix reaches the current target length, print it.

c
1#include <stdio.h>
2
3void generate_fixed_length(const char *alphabet, int alphabet_size,
4                           char *buffer, int depth, int target_length) {
5    if (depth == target_length) {
6        buffer[depth] = '\0';
7        printf("%s\n", buffer);
8        return;
9    }
10
11    for (int i = 0; i < alphabet_size; ++i) {
12        buffer[depth] = alphabet[i];
13        generate_fixed_length(alphabet, alphabet_size, buffer, depth + 1, target_length);
14    }
15}
16
17int main(void) {
18    const char alphabet[] = {'a', 'b', 'c'};
19    char buffer[4];
20
21    generate_fixed_length(alphabet, 3, buffer, 0, 3);
22    return 0;
23}

This generates all strings of exactly length 3.

Extend It to All Lengths Up To N

To generate strings under length N, call the fixed-length generator for each target length from 1 to N.

c
1#include <stdio.h>
2
3void generate_fixed_length(const char *alphabet, int alphabet_size,
4                           char *buffer, int depth, int target_length) {
5    if (depth == target_length) {
6        buffer[depth] = '\0';
7        printf("%s\n", buffer);
8        return;
9    }
10
11    for (int i = 0; i < alphabet_size; ++i) {
12        buffer[depth] = alphabet[i];
13        generate_fixed_length(alphabet, alphabet_size, buffer, depth + 1, target_length);
14    }
15}
16
17void generate_up_to_length(const char *alphabet, int alphabet_size, int max_length) {
18    char buffer[128];
19
20    for (int length = 1; length <= max_length; ++length) {
21        generate_fixed_length(alphabet, alphabet_size, buffer, 0, length);
22    }
23}
24
25int main(void) {
26    const char alphabet[] = {'0', '1'};
27    generate_up_to_length(alphabet, 2, 3);
28    return 0;
29}

That prints all non-empty binary strings up to length 3.

Include the Empty String Only If You Mean To

Some definitions of "under length N" include the empty string. Others do not. If you want it, print it explicitly before the main loop.

c
printf("\n");

Whether that is correct depends on the problem statement. It is better to decide explicitly than to accidentally include or exclude it.

Prefer Streaming Output to Storing Everything

Because the number of strings grows exponentially, storing them all is rarely the best approach. Printing, hashing, testing, or sending each generated string to a callback is usually more memory-friendly than building a huge list.

A callback-style interface looks like this:

c
1#include <stdio.h>
2
3typedef void (*string_consumer)(const char *);
4
5void consume(const char *s) {
6    printf("%s\n", s);
7}

Then call consume(buffer) instead of printf inside the recursion. That makes the generator reusable for testing, search, or filtering.

Time Complexity Matters More Than Recursion Overhead

The recursive overhead is not the real cost here. The real cost is the number of outputs.

If the alphabet size is k and the maximum length is N, the total number of generated strings is exponential in N. No implementation can avoid that if it must actually enumerate every string.

The goal of a good implementation is therefore not to make an exponential problem magically fast. It is to avoid unnecessary extra work and extra memory.

Common Pitfalls

The biggest mistake is forgetting to null-terminate the buffer before printing it as a C string. Another common issue is allocating a buffer that is too small for the maximum length plus the terminating null character. Developers also sometimes store every generated string even though the output count is exponential, which wastes memory quickly. Finally, be explicit about whether length 0 should be included so the function matches the real requirement.

Summary

  • Use recursive backtracking with a shared buffer to generate strings efficiently in C.
  • Generate fixed lengths first, then loop over lengths 1 through N for the full result.
  • Null-terminate the buffer before printing or consuming it.
  • Prefer streaming output or callbacks instead of storing every generated string.
  • Remember that the total number of generated strings grows exponentially with N.

Course illustration
Course illustration

All Rights Reserved.