【问题标题】:Missing the second node while printing a list of filenames: why?打印文件名列表时缺少第二个节点:为什么?
【发布时间】:2018-06-29 15:44:36
【问题描述】:

我有以下字符串(文件名)的列表:{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 '\0'
        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("%s\n", 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 = %s\n", tmp);,我会得到以下输出:

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

这里有一个link 用于包含我为此使用的所有代码的程序。如果我运行这个测试,它会按预期工作......但是如果我尝试在我的程序生成的列表上运行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/

【问题讨论】:

  • 我使用get_file_list() 填充了它,但正如您所见,我使用file_list_print()file_list_tostring() 得到了两个不同的结果
  • 我按照您在此处的建议创建了一个 MCVE:pastebin.com/uqySHGr3 有趣的是,它在这里再次正常工作!我真的不明白问题可能是什么......像这样继续下去,我最终可能会编写我项目的所有代码,我认为这篇文章对stackoverflow没有用处:/

标签: c string concatenation


【解决方案1】:

考虑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 数组,其中opendir malloc,但closedir 释放。在调用closedir 后,它以及其中的所有内容(包括名称)都将不复存在。

欢迎来到 UB。

【讨论】:

  • 感谢您的回答!那肯定会解释它:)你建议我如何解决它?编辑file_node_init?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多