file-handling · beginner · ~10 min

Extract the final path component

Find the last separator and copy the tail safely.

Challenge

Pull the filename out of a path — everything after the last / — without the surprising in-place behaviour of libc's basename().

Task

Implement int basename_of(const char *path, char *out, size_t cap) that copies the part of path following the last / into out (NUL-terminated, bounded by cap).

Input

  • path: a file path (NUL-terminated).
  • out / cap: destination buffer and its size.

Output

Return the number of bytes written to out. A path with no / is its own basename. Return -1 if path/out is NULL or the result doesn't fit in cap.

Example

basename_of("/a/b/file.txt", out, 64)   ->   8,  out = "file.txt"
basename_of("plain.c", out, 64)          ->   out = "plain.c"
basename_of("/etc/", out, 64)            ->   out = ""   (trailing slash)

Edge cases

  • No slash: the whole path is the basename.
  • Trailing slash: empty basename.
  • Output buffer too small: -1.

Rules

  • Find the last / (e.g. strrchr) and copy what follows; bound the copy by cap.

Why this matters

Pulling the filename out of a path is a constant chore — and doing it by hand avoids the surprising in-place behaviour of libc basename().

Input format

path: a file path. out/cap: result buffer and size.

Output format

int bytes written to out (final path component), or -1 on NULL / overflow.

Constraints

Basename is the text after the last /; trailing slash gives an empty result.

Starter code

#include <stddef.h>
int basename_of(const char *path, char *out, size_t cap) {
    /* TODO */
    (void)path; (void)out; (void)cap;
    return -1;
}

Common mistakes

Including the slash. Mishandling a trailing slash. No overflow guard.

Edge cases to handle

No slash. Trailing slash → empty string. Tiny buffer.

Complexity

O(path length).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.