As part of learning C, I wrote the following code to combine directory name with file name. Eg: combine("/home/user", "filename")
will result in /home/user/filename
. This function is expected work across platforms (atleast on all popular linux distributions and windows 32 and 64bit).
Here is the code.
const char* combine(const char* path1, const char* path2)
{
if(path1 == NULL && path2 == NULL) {
return NULL;
}
if(path2 == NULL || strlen(path2) == 0) return path1;
if(path1 == NULL || strlen(path1) == 0) return path2;
char* directory_separator = "";
#ifdef WIN32
directory_separator = "\\";
#else
directory_separator = "/";
#endif
char p1[strlen(path1)]; // (1)
strcpy(p1, path1); // (2)
char *last_char = &p1[strlen(path1) - 1]; // (3)
char *combined = malloc(strlen(path1) + 1 + strlen(path2));
int append_directory_separator = 0;
if(strcmp(last_char, directory_separator) != 0) {
append_directory_separator = 1;
}
strcpy(combined, path1);
if(append_directory_separator)
strcat(combined, directory_separator);
strcat(combined, path2);
return combined;
}
I have the following questions regarding the above code.
- Consider the lines numbered 1,2,3. All those 3 lines are for getting the last element from the string. It looks like I am writing more code for such a small thing. What is the correct method to get the last element from the
char*
string. - To return the result, I am allocating a new string using
malloc
. I am not sure this is the right way to do this. Is caller expected to free the result? How can I indicate the caller that he has to free the result? Is there a less error prone method available? - How do you rate the code (Poor, Average, Good)? What are the areas that can be imrpoved?
Any help would be great.
Edit
Fixed all the issues discussed and implemented the changes suggested. Here is the updated code.
void combine(char* destination, const char* path1, const char* path2)
{
if(path1 == NULL && path2 == NULL) {
strcpy(destination, "");;
}
else if(path2 == NULL || strlen(path2) == 0) {
strcpy(destination, path1);
}
else if(path1 == NULL || strlen(path1) == 0) {
strcpy(destination, path2);
}
else {
char directory_separator[] = "/";
#ifdef WIN32
directory_separator[0] = '\\';
#endif
const char *last_char = path1;
while(*last_char != '\0')
last_char++;
int append_directory_separator = 0;
if(strcmp(last_char, directory_separator) != 0) {
append_directory_separator = 1;
}
strcpy(destination, path1);
if(append_directory_separator)
strcat(destination, directory_separator);
strcat(destination, path2);
}
}
In the new version, caller has to allocate enough buffer and send to combine
method. This avoids the use of malloc
and free
issue. Here is the usage
int main(int argc, char **argv)
{
const char *d = "/usr/bin";
const char* f = "filename.txt";
char result[strlen(d) + strlen(f) + 2];
combine(result, d, f);
printf("%s\n", result);
return 0;
}
Any suggestions for more improvements?