There are basename
/ dirname
functions in POSIX. Their return value will point to either static memory or some suffix of the input, so there's no need to free it. This may be way easier than to split the string yourself:
// assuming you own *path:
char *file = basename(path);
char *dir = dirname(path); //that's all!
They also handle the special case when path
is "."
or ".."
or "foo/"
(then, basename is "."
- the correct thing).
But beware if you don't own the string: They take a non-const argument, and they may modify it.
If you really need to use basename
on a const char *
, the solution is about the same
#include <libgen.h> // POSIX
void die(const char * errormessage);
/* version of basename(3) that does not modify its argument.
* This assumes that "path" is correctly 0-terminated!
* Please free() the return value after use. */
char * basename_safe(const char * path)
{
char * result;
char * what_basename_says;
if (!path) {
// return a pointer to ".":
result = malloc(2 * sizeof(char));
if (!result) die("malloc failed!");
result[0] = '.';
result[1] = 0;
return result;
}
// in case path is the empty string, we need 2 chars to store the result ".",
// so add 2:
result = malloc((2 + strlen(path)) * sizeof(char));
if (!result) die("malloc failed");
// basename wants write access to its argument:
strcpy(result, path);
what_basename_says = basename(result);
// now what_basename_says actually may be a pointer into *result.
strcpy(result, what_basename_says);
// to allow for free(result)
return result;
}
But, as I said before: if you know that you can modify *path
, you may as well use basename
without all this.