I’ve been writing a small C application that operates on files, and I’ve found that I have been copy+pasting this code around my functions:
char fullpath[PATH_MAX];
fullpath[0] = '';
strcat(fullpath, BASE_PATH);
strcat(fullpath, subdir);
strcat(fullpath, "/");
strcat(fullpath, filename);
// do something with fullpath...
Is there a better way? The first thought that comes to mind is to create a macro but I’m sure this is a common problem in C, and I’m wondering how others have solve it.
7
Reusable for a function like the one you describe means several things:
- Doesn’t assume the input is valid.
- Uses sane defaults.
- Prevents buffer overruns.
- Returns some indication of success or failure.
In your case:
#define BASE_PATH "/path/to/wherever"
bool build_path(char *dest, size_t size, char *subdir, char *filename)
{
// Don't assume the input is valid
if ( (dest == NULL) || (size < 1) || (filename == NULL) ) {
return false;
}
// Make no subdir work (sane default behavior)
if ( subdir == NULL ) {
subdir = "";
}
// Prevent buffer overruns by using a safe formatting function
size_t stored = snprintf(dest, size, BASE_PATH "/%s/%s", subdir, filename);
// Returns success (true) if the path fit the buffer
return ((stored+1) <= size);
}
char fullpath[PATH_MAX];
if ( ! build_path(fullpath, sizeof(fullpath), "foo/bar", "baz") ) {
// Handle error
}
1
How about passing the address of fullpath
, subdir
, and filename
into a function and have that function concatenate all of the strings for you?
Something to the effect of:
void main(...)
{
char fullpath[PATH_MAX];
memset(fullpath, 0x00, PATH_MAX); //note: probably wrong syntax for memset
...
ConcatPath(&fullpath, subdir, filename);
}
ConcatPath(char *fullpath, char *subdir, char *filename)
{
strcat(fullpath, BASE_PATH); //note need some casting magic here to reference
strcat(fullpath, subdir); // fullpath & other strings correctly.
strcat(fullpath, "/");
strcat(fullpath, filename);
}
6
In my opinion, as a professional programmer, you must not write code like that. You must either write your own path concatenation function, or use the one provided by the platform.
If it’s Windows you should use the _makepath
function. For greater safety, use the _makepath_s
function. It will be more careful than you are. I’m sure Posix has something similar.
If you must write your own, simple concatenation is just not good enough. You need to check for proper handling of delimiters, trailing slash on directories, leading period on extensions, null arguments and all that stuff. The good news is that if you do it once it’s done.
In the more general case of concatenating strings, you are very hampered by your apparent decision to stick with C rather than C++. I would again recommend writing your own function with variable arguments (vararg
) and using strcat_s()
for security. Something like:
bool strcat_multi_s(char *destination, size_t maxlength, ...); // return false on overflow
I leave the coding as an exercise for the reader.