Как скопировать символ в вектор *

Я использую dirent для чтения имен файлов из определенной папки, и я хочу сохранить имена в символьном * векторе. Кажется, что он копирует некоторые странные символы вместо того, чтобы копировать имена файлов. Это то, что я пробовал до сих пор:

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 ответа

Решение

Как сказал пользователь 2079303, второй вызов 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* позже.

Замещать std::vector<char*> с std::vector<std::string>, И добавить #include <string>, Это должно решить проблему.

Кажется, что вы еще не поняли концепцию указателей и массивов в C/C++, и я не уверен, объясняю ли это, что вписывается в рамки SO-ответа. Но этот ответ может быть полезен: C++: копирует ли указатель char на преобразование std::string содержимое?

Короче говоря, проблема с вашим кодом заключается в том, что вместо копирования памяти, в которой хранится строка (сами символы, char[PATH_MAX]), вы только копировали указатель на эту память (char*). И указанный ранее блок памяти был повторно использован или даже удален, в результате чего сохраненный указатель стал недействительным.

Вам нужно хранить копии строки. использование vector<string>, Когда ты push_back(dp->d_name) вы храните висячий указатель, потому что dp выходит из области видимости после завершения функции.

Это потому, что вы нажимаете указатель, dp->d_name на вектор, однако строка, на которую указывает этот указатель, исчезает при вызове следующего readdir() вызов.

Вместо этого вы должны сделать копию этой строки и вставить ее в вектор:

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

Теперь вы должны не забыть освободить () эту строку, которая копируется в вектор, когда вы закончите с filenames вектор

Однако, пожалуйста, не делайте этого вообще. Просто используйте:

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

И вы можете использовать свой оригинальный код здесь, и об управлении памятью позаботятся.

Другие вопросы по тегам