C语言 打印文件名列表时缺少第二个节点:为什么?



我有一个以下字符串(文件名)的列表:{Lorem.ipsum, dolor-sit-amet, SENDME, LOREM2, consectetur, adipiscing.elit}. 我编写了这个函数,它应该获取列表的每个节点并生成一个由所有文件名组成的字符串(在每个条目之间插入/)。

char *file_list_tostring(struct file_list *file_list) {
char *final_string = NULL;
size_t final_len = 0;
struct file_node *list_iter = file_list->first;
while (list_iter != NULL) {
char *tmp = concat(list_iter->filename, "/");
size_t tmp_len = strlen(tmp);
char *s = realloc(final_string, final_len + tmp_len + 1); // +1 for ''
if (s == NULL) {
perror("realloc");
exit(EXIT_FAILURE);
}
final_string = s;
memcpy(final_string + final_len, tmp, tmp_len + 1);
final_len += tmp_len;
list_iter = list_iter->next;
}
printf("%sn", final_string);
return final_string;
}

以下是concat()函数的实现:

char *concat(const char *s1, const char *s2) {
char *result = malloc(strlen(s1) + strlen(s2) + 1); //+1 for the null-terminator
if (result == NULL) {
perror("malloc");
return NULL;
}
strcpy(result, s1);
strcat(result, s2);
return result;
}

如果我运行file_list_tostring()我会得到以下输出:

Lorem.ipsum/SENDME/LOREM2/consectetur/adipiscing.elit/

如您所见,列表的第二个条目 (dolor-sit-amet) 没有出现。这真的让我感到惊讶!原因可能是什么?

注意:无论我尝试什么文件名列表,它总是跳过第二个。

以下是定义列表的结构:

struct file_node {
char *filename;
struct file_node *prev, *next;
};
struct file_list {
struct file_node *first, *last;
};

编辑

如果我在char *tmp = concat(list_iter->filename, "/");后立即添加printf("tmp = %sn", tmp);,我会得到以下输出:

tmp = Lorem.ipsum/
tmp = 
tmp = SENDME/
tmp = LOREM2/
tmp = consectetur/
tmp = adipiscing.elit/

这是一个程序的链接,其中包含我用于此目的的所有代码。如果我运行此测试,它会按预期工作...但是如果我尝试在我的程序生成的列表中运行file_list_print(),后来file_list_tostring我会得到不同的结果(如前所述,缺少第二个条目)。我必须假设列表未正确生成(当它在测试文件中时)。

所以这是我用来获取列表的代码(它应该获取repository目录中的所有文件名):

struct file_list *get_file_list() {
struct file_list *list = file_list_init();
DIR *d;
struct dirent *dir;
d = opendir("./repository");
if (d == NULL)
return NULL;
while ((dir = readdir(d)) != NULL) {
struct file_node *newnode;
if (!(!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) && dir->d_type == DT_REG) {
newnode = file_node_init(dir->d_name);
file_node_add(list, newnode);
}
}
closedir(d);
return list;
}

我尝试更改目录中的所有文件,这次我得到以下 2 个输出:

0: FILEC
1: FILEE
2: FILEB
3: FILED
4: FILEA
tmp = FILEC/
tmp = 
tmp = 
tmp = FILED/
tmp = FILEA/
FILEC/FILED/FILEA/

考虑一下file_node_init是如何实现的:

struct file_node *file_node_init(char *filename) {
struct file_node *node = malloc(sizeof(struct file_node));
if (node == NULL)           // Error in malloc
return NULL;
node->filename = filename;
node->prev = NULL;
node->next = NULL;
return node;
}

请注意,node->filename不是分配的,而是引用get_file_listdird_name字段。到目前为止一切顺利,但请记住,每个dir都属于d数组,该数组opendirmallocs,但closedir释放closedir被调用后,它以及其中的所有内容(包括名称)都不复存在。

欢迎来到 UB。

最新更新