我有一个名为
的班级Array<T>
您可以创建任何类型的数组。
template <typename T>
class Array
{
private:
T *m_array;
int m_size;
...
例如,
Array <int> myArray(32)
是int类型的数组,大小为32.这可以存储基本类型或复杂对象。例如,
Array<Monster> monsters(32)
可以容纳一组怪物对象。无论使用什么类型,我都想从磁盘保存并加载数组。
其中一个对象,比如Actor,有一个std :: string类型的成员变量(名称)。因此,它存储为
Array<Actor> actors(32)
我今天意识到C的I / O函数对std :: string一无所知,所以从文件加载std :: string导致关闭时崩溃。我想将我的保存/加载功能升级到C ++的等价物。我的假设是这将解决我的问题,即保存和加载具有类型为std :: string的成员变量的对象。
我原来的保存/加载功能: (因为模板的工作方式,它们位于标题中,我应该提到它们是更正式的Array成员,或Array :: save()和Array :: load()。)
bool save(const string filename)
{
FILE *fOut = NULL;
int written = 0;
// Validate the array
if (!isValidArray())
return false;
// Open the file
fOut = fopen(filename.c_str(), "wb");
if (fOut == NULL)
return false;
// Write the array's size to file.
fwrite(&m_size, sizeof(int), 1, fOut);
// Write the array to file.
written = fwrite(m_array, sizeof(T), m_size, fOut);
fclose(fOut);
// Validate if the array was written correctly
if (written != m_size)
return false;
return true;
}
负载:
bool load(const string filename)
{
FILE *fIn = NULL;
int read = 0;
int size = 0;
// Open the file
fopen_s(&fIn, filename.c_str(), "rb");
if (fIn == NULL)
return false;
// Read the array's size from file.
fread(&size, sizeof(int), 1, fIn);
// Rleease the old array
release();
// Initialize the new array
if (!init(size))
return false;
// Read the array from file.
read = fread(m_array, sizeof(T), size, fIn);
fclose(fIn);
// Validate if the array was written correctly.
// If not, clean up the array object.
if (read != size)
{
if (m_array != NULL)
{
delete[] m_array;
m_array = NULL;
m_size = 0;
}
return false;
}
return true;
}
总的来说,我想将这些转换为C ++的文件处理。
这是我使用save()的C ++尝试:
bool save(const string filename)
{
ofstream fOut;
// Validate the array
if (!isValidArray())
return false;
// Open the file
fOut.open(filename.c_str(), std::ios::binary | std::ios::out);
if (!fOut.is_open())
return false;
// Write the array's size to file.
fOut << m_size;
// Write the array to file. ????
fOut.write(m_array, m_size);
fOut.close();
return true;
}
所以,我的问题是当模板类型可以是基本数据类型,结构或类时,如何将数组保存到文件中。我的第一个假设是:
// Write the array to file. ????
fOut.write(m_array, m_size);
任何想法都会有所帮助。谢谢。
发现我需要序列化,我重载了运算符&lt;&lt;对于我的Actor类,但希望进一步指导如何将其用于此目的。 Actor有一个我需要保存到文件的std :: string。
std::ofstream & X2D::operator<<(std::ofstream & output, const Actor & p)
{
// insert magical code here
return output;
}
答案 0 :(得分:0)
考虑让您的save
函数成为Array的成员并根据需要重载它。您可能会发现C ++ 11中的std::enable_if
功能非常有用,只允许对代码准备好的类型进行序列化。您的
fOut.write(m_array, m_size);
无法从头开始工作,您需要自己实施。截至撰写本文时,C ++在这方面仍然不是Java。
答案 1 :(得分:0)
这最终成为我的解决方案。重载运算符&lt;&lt;和&gt;&gt;帮助我的课程在保存时保持灵活性。
我会发布下面的代码,以防它对任何人都有用。字符串保存看起来有点混乱,可能会有所改进,但它成功保存/加载长度,然后保存/加载std :: string。
std::ostream& operator<<(std::ostream& os, const Monster& obj)
{
int length = obj.m_name.length() + 1;
char buffer[1080];
strcpy_s(buffer, 1080, obj.m_name.c_str());
os << length;
os.write(buffer, strlen(buffer) + 1);
os << endl;
os << obj.m_x << endl;
os << obj.m_y << endl;
os << obj.m_hp << endl;
return os;
}
std::istream& operator>>(std::istream& is, Monster& obj)
{
int length;
char buffer[1080];
is >> length;
is.readsome(buffer, length);
std::string sBuffer(buffer, length);
obj.m_name = sBuffer;
is >> obj.m_x;
is >> obj.m_y;
is >> obj.m_hp;
return is;
}