作为学习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;
}
关于上述代码,我有以下问题。
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;
}
有任何进一步改进的建议吗?
最佳答案
并且存在内存泄漏:
const char *one = combine("foo", "file");
const char *two = combine("bar", "");
//...
free(one); // needed
free(two); // disaster!
编辑:您的新代码看起来更好。一些小的样式更改:
;;
。strlen(path2) == 0
替换为path2[0] == '\0''
或仅替换为!path2[0]
。 last_char
的循环,并使用const char last_char = path1[strlen(path1) - 1];
if(append_directory_separator)
更改为if(last_char != directory_separator[0])
。因此,您不再需要变量append_directory_separator
。 destination
,类似于strcpy(dst, src)
,它返回dst
。 编辑:并且您的
last_char
循环存在一个错误:它始终返回path1
的结尾,因此您可能在答案中以双斜杠//结束。 (但是Unix除非将它放在开始,否则将其视为一个斜杠)。无论如何,我的建议解决了这个问题-我认为这与jdmichal的答案非常相似。而且我发现您在原始代码中具有此正确性(我承认我只是看了一眼-太复杂了,以我的口味;您的新代码要好得多)。还有另外两个主观意见:
stpcpy()
,以避免strcat()
的效率低下。 (如果需要,可以轻松编写自己的代码。)strcat()
等不安全的观点非常强烈。但是,我认为您的用法非常好。 关于合并目录和文件路径-C,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3142365/