gpt4 book ai didi

c++ - 将 vector 加载和保存到文件

转载 作者:行者123 更新时间:2023-11-30 04:24:57 24 4
gpt4 key购买 nike

我正在使用 C++ Builder,我有一个 Appointment 对象的 vector 数组。

我想将它保存到文件中并从文件中加载它。

目前,我正在对二进制文件使用 ifstream 和 ofstream。我有一个 header ,其中包含将与数据一起保存的 vector 大小,以便在加载时了解其大小。

序列化是更好的方法吗?

如果是这样,我需要使用 boost 库还是其他方式?

这是我当前的代码:

class appointment
{
public:
appointment();
appointment(TDateTime aDate, TDateTime aReminderDateTime, string aType,
string aLocation, string aComments, bool aIsImportant)
{
appDateTime = aDate;
appReminderDateTime = aReminderDateTime;
appType = aType;
appLocation = aLocation;
appComments = aComments;
appIsImportant = aIsImportant;
}
void setAppDateTime(TDateTime aDateTime)
{
appDateTime = aDateTime;
}
void setappReminderDateTime(TDateTime aReminderDateTime)
{
appReminderDateTime = aReminderDateTime;
}
/*
void printAppointmentDetails()
{
cout << "Appointment Date: " << appDateTime << endl;
cout << "Appointment Reminder Date: " << appReminderDateTime << endl;
cout << "Appointment Type: " << appType << endl;
cout << "Appointment Location: " << appLocation << endl;
cout << "Appointment Comments: " << appComments << endl;
if (appIsImportant)
{
cout << "Appointment IsImportant: " << "Yes" << endl;
} else {
cout << "Appointment IsImportant: " << "No" << endl;
}
}

*/
void setType(string aType)
{
appType = aType;
}
void setLocation(string aLocation)
{
appLocation = aLocation;
}
void setComments(string aComments)
{
appComments = aComments;
}
void setIsImportant(bool aIsImportant)
{
appIsImportant = aIsImportant;
}
TDateTime getAppDateTime()
{
return appDateTime;
}
TDateTime getAppReminderDateTime()
{
return appReminderDateTime;
}
string getType()
{
return appType;
}
string getLocation()
{
return appLocation;
}
string getComments()
{
return appComments;
}
bool getIsImportant()
{
return appIsImportant;
}
private:
//appointment();
TDateTime appDateTime;
TDateTime appReminderDateTime;
string appType;
string appLocation;
string appComments;
bool appIsImportant;
//person owner;
};

class calendar
{
public:
calendar()
{
//loadFromFile();
//load persons
//calculateimportantAppointments
}
~calendar()
{
saveToFile();
}
//addperson
//editperson
//removeperson
void createAppointment(TDateTime aDate, TDateTime aReminderDateTime, string aType,
string aLocation, string aComments, bool aIsImportant)
{
appointment newAppointment(aDate, aReminderDateTime, aType,
aLocation, aComments, aIsImportant);
appointments.push_back(newAppointment);
}
/*
void printAllAppointmentDetails()
{
for (int i = 0; i < appointments.size(); i++)
{
appointments[i].printAppointmentDetails();
}
}
void calculateImportantAppointments()
{

}
int getNumberOfImportantAppointments()
{
int intImportantAppointmentCount = 0;
for (int i = 0; i < appointments.size(); i++)
{
if (appointments[i].getIsImportant())
intImportantAppointmentCount += 1;
}
return intImportantAppointmentCount;
}

appointment[] getImportantAppointments()
{

}
appointment[] getAllAppointments()
{

}
*/
void loadFromFile()
{
ifstream iStream("file.ext", ios::binary);
if (!iStream)
{
cout << "No file";
} else {
fileHeader_t fHeader;
iStream.read((char*)&fHeader, sizeof(fileHeader_t));
if (fHeader.magicNumber = 0xDEADBEAF)
{
appointments.resize(fHeader.appointmentCount);
iStream.read((char*)&appointments[0], fHeader.appointmentCount * sizeof(appointment));
}
}
}
void saveToFile()
{
ofstream oStream("file.ext", ios::binary);
fileHeader_t fHeader;
fHeader.magicNumber = 0xDEADBEAF;
fHeader.appointmentCount = appointments.size();
oStream.write((char*)&fHeader, sizeof(fileHeader_t));
oStream.write((char*)&appointments[0], sizeof(appointment) * appointments.size());
}
//vector<appointment> appointments;
private:
vector<appointment> appointments;
string calCurrentDate;
string calCurrentTime;
typedef struct fileHeader_s
{
DWORD magicNumber;
size_t appointmentCount;
}fileHeader_t;
};

调用 loadFromFile() 方法时出现以下错误。

[BCC32 Warning] File1.cpp(185): W8060 Possibly incorrect assignment [ILINK32 Error] Error: Unresolved external 'appointment::appointment()' referenced from \PROFILES.SOIT.LOCAL\HOMES$\SIMON.CANNING\MY DOCUMENTS\RAD STUDIO\PROJECTS\DEBUG\FILE1.OBJ [ILINK32 Error] Error: Unable to perform link

我知道这是由于构造函数调用而发生的。我可以就如何解决此问题提出一些建议吗?

最佳答案

有了所有的戏剧,你可能会得到提升来编译,然后你必须做所有的废话来实现序列化,我个人不会打扰。

只需将大小设置到标题中,将其写入文件,然后写出 vector 的字节。

加载时,读入 header ,将 vector 调整为它所说的大小,然后读入 vector 的字节。

[编辑]

正如评论中所讨论的,您必须意识到您也不能将其他重要类型(例如字符串)写成二进制。所有这些都必须序列化。从您提出问题的方式,我推断您已经意识到了这一点。

所以如果你只需要序列化几个类型并且还没有使用boost,我个人认为使用boost来解决这个问题会有点大材小用。人们似乎对我表达这种观点的方式做出了负面 react ,所以也许他们从来没有处理过一个项目,在这个项目中,有人依赖于 boost 序列化来解决一个非常简单和孤立的问题 =)

您真正需要的是一些您可以自己编写的简单支持函数。在这种情况下,您甚至不需要该 header 来包含 vector 大小,因为您可以序列化...

// This writes a vector of trivial data types.
template <class T>
void WriteTrivial( std::ostream& s, const std::vector<T>& data )
{
unsigned int len = data.size();
s.write( (char*)&len, sizeof(len) );
s.write( (const char*)&data[0], len * sizeof(T) );
}

// This reads a vector of trivial data types.
template <class T>
void ReadTrivial( std::istream& s, std::vector<T>& data )
{
unsigned int len = 0;
s.read( (char*)&len, sizeof(len) );
data.resize(len);
if( len > 0 ) s.read( (char*)&data[0], len * sizeof(T) );
}

如果你的 vector 可能包含字符串或 vector ,你需要更多的支持函数

// This writes a vector of non-trivial data types.
template <class T>
void Write( std::ostream& s, const std::vector<T>& data )
{
unsigned int len = data.size();
s.write( (char*)&len, sizeof(len) );
for( unsigned int i = 0; i < len; i++ ) {
Write( s, data[i] );
}
}

// This reads a vector of non-trivial data types.
template <class T>
void Read( std::istream& s, std::vector<T>& data )
{
unsigned int len = 0;
s.read( (char*)&len, sizeof(len) );
data.resize(len);
for( unsigned int i = 0; i < len; i++ ) {
Read( s, data[i] );
}
}

当然,对于上述内容,您还需要一些用于字符串的内容,以及一个用于处理普通数据类型的读/写模板。无论如何,这应该可以帮助您入门。希望对您有所帮助。

[编辑]

既然您已经发布了代码,我建议您这样做:

日历中:

void loadFromFile()
{
ifstream iStream("file.ext", ios::binary);
if (!iStream)
{
cout << "No file";
} else {
fileHeader_t fHeader;
iStream.read((char*)&fHeader, sizeof(fileHeader_t));
if (fHeader.magicNumber != 0xDEADBEAF) return;
appointments.resize(fHeader.appointmentCount);
for( size_t i = 0; i < appointments.size(); i++ ) {
appointments[i].read(iStream);
}
iStream.close();
}
}

void saveToFile()
{
ofstream oStream("file.ext", ios::binary);
fileHeader_t fHeader;
fHeader.magicNumber = 0xDEADBEAF;
fHeader.appointmentCount = appointments.size();
oStream.write((char*)&fHeader, sizeof(fileHeader_t));
for( size_t i = 0; i < appointments.size(); i++ ) {
appointments[i].write(oStream);
}
oStream.close();
}

现在,序列化字符串:

void write( ostream &s, const string& str )
{
unsigned int len = str.size();
s.write((char*)&len, sizeof(len));
s.write(str.c_str(), len*sizeof(char));
}

void read( istream &s, string& str )
{
unsigned int len = 0;
s.read((char*)&len, sizeof(len));
str.resize(len);
if( len == 0 ) return;
s.read((char *) str.c_str(), len*sizeof(char));
}

也许是一个有用的包装器来编写普通类型:

template <class T>
void writeTrivial( ostream& s, const T& val )
{
ostream.write( (const char*)&val, sizeof(T) );
}

template <class T>
void readTrivial( ostream& s, T& val )
{
ostream.read( (char*)&val, sizeof(T) );
}

最后,在约会

void write( ostream& s )
{
writeTrivial(s, appDateTime);
writeTrivial(s, appReminderDateTime);
write(s, appType);
write(s, appLocation);
write(s, appComments);
writeTrivial(s, appIsImportant);
}

void read( istream& s )
{
readTrivial(s, appDateTime);
readTrivial(s, appReminderDateTime);
read(s, appType);
read(s, appLocation);
read(s, appComments);
readTrivial(s, appIsImportant);
}

关于c++ - 将 vector 加载和保存到文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12416175/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com