Как скопировать символ в вектор *
Я использую 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;
И вы можете использовать свой оригинальный код здесь, и об управлении памятью позаботятся.