Lesson 23 of 23

tree

The tree Command

tree prints a directory hierarchy with connectors showing which items belong together:

.
+-- Makefile
+-- README.md
+-- src
|   +-- lib.c
|   '-- main.c
'-- tests
    '-- test.c

Your Implementation

Write void my_tree(const char *paths) that takes a newline-separated, sorted list of paths and prints them as a tree.

The input uses / as a separator: "src/lib.c" means lib.c lives inside src. The output is always rooted at ..

The key insight: recursive helper function. print_dir receives the full path array and finds all direct children of a given prefix, then recurses into any subdirectories.

int has_prefix(char lines[][256], int i, const char *pre, int plen) {
    for (int k = 0; k < plen; k++)
        if (lines[i][k] != pre[k]) return 0;
    return 1;
}

void print_dir(char lines[][256], int n,
               const char *parent, int plen, const char *indent) {
    // Collect direct children: start with parent, no '/' in remainder
    int ch[64], cc = 0;
    for (int i = 0; i < n; i++) {
        if (!has_prefix(lines, i, parent, plen)) continue;
        const char *rest = lines[i] + plen;
        int slash = 0;
        while (*rest) { if (*rest == '/') { slash = 1; break; } rest++; }
        if (!slash) ch[cc++] = i;
    }
    for (int ci = 0; ci < cc; ci++) {
        int i = ch[ci];
        int last = (ci == cc - 1);
        printf("%s%s %s\n", indent, last ? "'--" : "+--", lines[i] + plen);
        // Build child prefix: path + '/'
        char np[256]; int npl = 0;
        while (lines[i][npl]) { np[npl] = lines[i][npl]; npl++; }
        np[npl++] = '/'; np[npl] = '\0';
        // Recurse if it has children
        int has_ch = 0;
        for (int j = 0; j < n; j++)
            if (has_prefix(lines, j, np, npl)) { has_ch = 1; break; }
        if (has_ch) {
            char ni[256]; int ii = 0;
            while (indent[ii]) { ni[ii] = indent[ii]; ii++; }
            const char *ext = last ? "    " : "|   ";
            while (*ext) ni[ii++] = *ext++;
            ni[ii] = '\0';
            print_dir(lines, n, np, npl, ni);
        }
    }
}

void my_tree(const char *paths) {
    char lines[64][256];
    int n = 0;
    while (*paths) {
        char *out = lines[n];
        while (*paths && *paths != '\n') *out++ = *paths++;
        *out = '\0';
        if (*paths == '\n') paths++;
        n++;
    }
    printf(".\n");
    print_dir(lines, n, "", 0, "");
}

How It Works

  1. Parse paths into a local 2D array lines[64][256]
  2. print_dir receives the full array and its size, plus the current prefix and indent
  3. It finds direct children — entries starting with prefix that have no extra / in the remainder
  4. For each child: print +-- or '--, then recurse if it has children, extending the indent with "| " (non-last) or " " (last)

Passing lines and n as parameters (rather than globals) keeps all state local to my_tree.

Your Task

Implement my_tree that prints the path list as a directory tree rooted at ..

TCC compiler loading...
Loading...
Click "Run" to execute your code.