Nav*_*K N 8 c string refactoring
作为学习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;
}
Run Code Online (Sandbox Code Playgroud)
关于上面的代码我有以下问题.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
在新版本中,调用者必须分配足够的缓冲区并发送给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;
}
Run Code Online (Sandbox Code Playgroud)
有任何改进的建议吗?
并且存在内存泄漏:
const char *one = combine("foo", "file");
const char *two = combine("bar", "");
//...
free(one); // needed
free(two); // disaster!
Run Code Online (Sandbox Code Playgroud)
编辑:您的新代码看起来更好。一些小的样式更改:
;;第4行中的双分号。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。编辑:并且for的循环last_char有一个bug:它始终返回的结尾path1,因此您可能在答案中以双斜杠//结尾。(但是Unix除非将它放在开始,否则将其视为一个斜杠)。无论如何,我的建议解决了这个问题-我认为这与jdmichal的答案非常相似。而且我看到您的原始代码中有正确的内容(我承认我只是看了一眼-太复杂了,以我的口味;您的新代码要好得多)。
还有另外两种主观意见:
stpcpy()来避免效率低下strcat()。(如果需要,可以自己写。)strcat()之类的事物有非常强烈的看法。但是,我认为您的用法非常好。