2

我正在使用 dirent 从特定文件夹中读取文件名,并且我想将名称保存在 char* 向量中。它似乎是在复制一些奇怪的符号而不是复制文件名。这是我到目前为止所尝试的:

std::vector<char*> filenames;

int filenamesAndNumberOfFiles(char *dir)
{
    struct dirent *dp;
    DIR *fd;
    int count = 0;

    if ((fd = opendir(dir)) == NULL) 
    {
        fprintf(stderr, "listdir: can't open %s\n", dir);
        return 0;
    }
    while ((dp = readdir(fd)) != NULL) 
    {
        if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
            continue;    /* skip self and parent */
        printf("Filename: %s\n", dp->d_name);
        filenames.push_back(dp->d_name);
        count++;
    }
    closedir(fd);
    return count;
}

谁能告诉我为什么它不复制文件名,我该怎么做才能复制它们?

编辑: d_name 是一个 char 变量,声明为:

char d_name[PATH_MAX];

似乎在我的程序中 PATH_MAX 等于 260。

PS:我是第一次使用dirent,所以不是很熟悉。

4

4 回答 4

6

替换std::vector<char*>std::vector<std::string>。并添加#include <string>. 那应该可以解决问题。

似乎您还没有掌握 C/C++ 中指针和数组的概念,我不确定解释这是否符合 SO 答案的限制。但是这个答案可能有用:C++:指向 std::string 转换的 char 指针会复制内容吗?

简而言之,您的代码的问题在于,您不是复制存储字符串的内存(字符本身,char[PATH_MAX]),而是复制指向该内存的指针(char*)。并且指向的内存块后来被重用甚至删除,使您存储的指针无效。

于 2016-01-13T09:29:50.297 回答
3

您需要存储字符串的副本。使用vector<string>. 当您push_back(dp->d_name)存储一个悬空指针时,因为dp函数结束后超出范围。

于 2016-01-13T09:30:25.170 回答
3

这是因为您将指针压入dp->d_name向量上,但是当您调用下一个调用时,该指针指向的字符串已消失readdir()

相反,您必须复制该字符串,并将其推送到向量上:

filenames.push_back(strdup(dp->d_name));

现在,你必须记住释放()这个字符串,当你完成你的向量时,这个字符串被复制到filenames向量中

但是,请不要这样做。只需使用:

std::vector<std::string> filenames;

你可以在这里使用你的原始代码,内存管理将得到处理。

于 2016-01-13T09:31:41.057 回答
1

正如 user2079303 所说,第二次调用 readdir 将覆盖第一次调用(链接)返回的结果。

但我建议您在 C++ 中为此使用字符串:

std::vector<std::string> filenames;

int filenamesAndNumberOfFiles(char *dir)
{
    struct dirent *dp;
    DIR *fd;
    int count = 0;

    if ((fd = opendir(dir)) == NULL) 
    {
        fprintf(stderr, "listdir: can't open %s\n", dir);
        return 0;
    }
    while ((dp = readdir(fd)) != NULL) 
    {
        if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
            continue;    /* skip self and parent */
        printf("Filename: %s\n", dp->d_name);
        filenames.push_back( std::string(dp->d_name) );
        count++;
    }
    closedir(fd);
    return count;
}

c_str()如果您以后需要,您可以随时使用char*

于 2016-01-13T09:38:14.583 回答