我编写了一个 C++ 函数,它使用“recursive_directory_iterator”来获取父文件夹中所有文件和文件夹的信息。然后我编写了一个名为 DataFolder 的类来存储每个文件的属性,例如文件大小、路径、名称、日期编号等。最后,我使用矢量对象来存储 DataFolder 对象的集合。
对于矢量对象,我使用push_back 添加DataFolder 对象。第一次分配有效,但是在后续尝试中,分配时没有内存或访问问题,但所有先前存储的项目中包含的数据都已损坏。只有最近添加的内容没有改变。
如何将 DataFolder 对象添加到我的 C++ STL Vector 对象并保留先前存储在向量中的数据?
这是我创建的函数:directory_base。
#include <iostream>
#include <filesystem>
#include <ctime>
#include <vector>
#include "CDir.h"
using namespace std;
using namespace std::filesystem;
// CDIR List folder.
// CDIR NAME lists the files in a folder.NAME must be specified as a
// character vector or string scalar.
//
// NAME can include a relative path, but the relative path must be in the
// current folder.Otherwise, NAME must include a full path.
//
// To list filesand folders at a remote location, NAME must contain a
// full path specified as a uniform resource locator(URL).
//
// Pathnamesand asterisk wildcards may be used in NAME.A single asterisk
// in the path touching only file separators will represent exactly one
// folder name.A single asterisk at the end of an input will represent
// any filename.An asterisk followed or preceded by characters will
// resolve to zero or more characters.A double asterisk can only be used
// in the path and will represent zero or more folder names.It cannot
// touch a character other than a file separator.For example, DIR* .m
// lists all files with a.m extension in the current folder.DIR*/*.m
// lists all files with a .m extension exactly one folder under the
// current folder. CDIR **/* .m lists all files with a.m extension zero or
// more folders under the current folder.
//
// D = CDIR('NAME') returns the results in an M - by - 1
// structure with the fields :
// name -- Filename
// folder -- Absolute path
// date -- Modification date
// bytes -- Number of bytes allocated to the file
// isdir-- 1 if name is a folder and 0 if not
// datenum -- Modification date as a MATLAB serial date number.
// This value is locale - dependent.
//
// See also WHAT, CD, TYPE, DELETE, LS, RMDIR, MKDIR, DATENUM.
// Copyright 1984 - 2019 The MathWorks, Inc.
// Built - in function.
static const char* convertIntToMonth(int imon)
{
if (imon == 1)
{
return "Jan";
}
else if (imon == 2)
{
return "Feb";
}
else if (imon == 3)
{
return "Mar";
}
else if (imon == 4)
{
return "Apr";
}
else if (imon == 5)
{
return "May";
}
else if (imon == 6)
{
return "Jun";
}
else if (imon == 7)
{
return "Jul";
}
else if (imon == 8)
{
return "Aug";
}
else if (imon == 9)
{
return "Sep";
}
else if (imon == 10)
{
return "Oct";
}
else if (imon == 11)
{
return "Nov";
}
else if (imon == 12)
{
return "Dec";
}
else if (imon < 1 || imon > 12)
{
return "OOR";
}
return "INV";
}
static double dateNumber(double year, int month, double day)
{
double cumdays[] = { 0, 0,31,59,90,120,151,181,212,243,273,304,334 };
double retval = 365 * year + cumdays[month] + day;
retval += year / 4;
return retval;
}
const vector<DataFolder>& directory_base(const char* path, vector<DataFolder>& datfldr)
{
int ii = 0;
cout << "Let put out the files!" << endl;
for (recursive_directory_iterator i(path), end; i != end; ++i)
{
if (!is_directory(i->path()))
{
if (is_regular_file(i->path()))
{
DataFolder df{};
filesystem::path df_name = i->path();
string fn = df_name.string();
df.name = new char[fn.length()];
df.name = const_cast<char*>(fn.c_str());
struct stat attrib {};
struct tm *clock = new tm();
stat(df.name, &attrib);
errno_t errNo = localtime_s(clock, &(attrib.st_mtime));
size_t fsz = file_size(df.name);
df.bytes = static_cast<int>(file_size(df_name));
string tmp = to_string(clock->tm_mday) + "-" +
convertIntToMonth(clock->tm_mon+1) + "-" + to_string(clock->tm_year+1900) + "
" + to_string(clock->tm_hour) + ":" + to_string(clock->tm_min) + ":" +
to_string(clock->tm_sec);
df.date = new char[tmp.length()];
df.date = const_cast<char*>(tmp.c_str());
df.datenum = dateNumber(static_cast<double>(clock->tm_year)+1900, clock-
>tm_mon+1, clock->tm_mday);
filesystem::path df_fldr = i->path().parent_path();
string ffldr = df_fldr.string();
df.folder = new char[ffldr.length()];
df.folder = const_cast<char*>(ffldr.c_str());
df.isdir = false;
cout << i->path().filename() << "\n";
cout << "\nData Folder Values" << endl;
cout << "df.name: " << df.name << endl;
cout << "df.date: " << df.date << endl;
cout << "df.bytes: " << df.bytes << endl;
cout << "df.datenum: " << df.datenum << endl;
cout << "df.folder: " << df.folder << endl;
cout << "df.df.isdir: " << df.isdir << endl;
datfldr.push_back(df);
}
}
}
return datfldr;
}
我希望数据看起来像这样:
相反,我得到了这个:
感谢您的时间和帮助。
问题是这三行:
string ffldr = df_fldr.string();
df.folder = new char[ffldr.length()];
df.folder = const_cast<char*>(ffldr.c_str());
第一行创建一个本地对象,一旦
if (is_regular_file(i->path()))
块结束,该对象将超出范围并被销毁。
第二行为
ffldr.length()
减去 1 字符的字符串分配内存,因为 C 样式字符串字符数组需要空间来容纳空终止符。
第三行覆盖您刚刚创建的指针,丢失您分配的内存。一旦区块结束,指针也会失效,
ffldr
的生命周期结束。
自然的 C++ 解决方案当然是使
DataFolder::folder
成为 std::string
。
如果由于某种原因不能这样,您首先需要分配
ffldr.length() + 1
字符并使用 std::strcpy
copy 字符串。