Как часть изучения C, я написал следующий код, чтобы объединить имя каталога с именем файла.Например: combine("/home/user", "filename")
приведет к /home/user/filename
.Ожидается, что эта функция будет работать на всех платформах (по крайней мере, во всех популярных дистрибутивах Linux и Windows 32 и 64-битных версиях).
Вот код.
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;
}
У меня есть следующие вопросы относительно приведенного выше кода.
- Рассмотрим строки с номерами 1,2,3.Все эти 3 строки предназначены для получения последнего элемента из строки.Похоже, я пишу больше кода для такой маленькой вещи.Как правильно получить последний элемент из строки
char*
. - Чтобы вернуть результат, я выделяю новую строку, используя
malloc
.Я не уверен, что это правильный способ сделать это.Ожидается ли, что вызывающий абонент освободит результат?Как я могу указать звонящему, что он должен освободить результат?Существует ли менее подверженный ошибкам метод? - Как вы оцениваете код (плохой, средний, хороший)?Какие области могут быть улучшены?
Любая помощь будет полезна.
Редактировать
Исправлены все обсуждаемые проблемы и реализованы предложенные изменения.Вот обновленный код.
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);
}
}
В новой версии вызывающая сторона должна выделить достаточно буфера и отправить в метод combine
.Это позволяет избежать использования проблем malloc
и free
.Вот использование
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;
}
Есть предложения по улучшению?