我遇到了一个小问题。我有一个结构体,其中包含一个向量。请注意,每次迭代都会动态生成这个向量。现在,在特定的迭代中,如何将包含大小为n的向量的结构体存储到二进制文件中?
此外,在检索时,假设我知道向量的大小,那么如何从二进制文件中检索出包含所有存储元素向量的结构变量?
我能够将一些内容存储到二进制文件中(因为我可以看到在写入时大小在增加),但是当我尝试检索元素时,我得到的向量大小为零。
不幸的是,我必须使用标准STL来实现这一点,并且不能使用任何第三方库。
我遇到了一个小问题。我有一个结构体,其中包含一个向量。请注意,每次迭代都会动态生成这个向量。现在,在特定的迭代中,如何将包含大小为n的向量的结构体存储到二进制文件中?
此外,在检索时,假设我知道向量的大小,那么如何从二进制文件中检索出包含所有存储元素向量的结构变量?
我能够将一些内容存储到二进制文件中(因为我可以看到在写入时大小在增加),但是当我尝试检索元素时,我得到的向量大小为零。
不幸的是,我必须使用标准STL来实现这一点,并且不能使用任何第三方库。
您应该看一下Boost Serialization。
如果您不能使用第三方库,那么您必须知道C++不支持直接序列化。这意味着您必须自己完成。
本文展示了一种将自定义对象序列化到磁盘并检索回来的好方法。而本教程则向您展示如何立即使用fstream开始。
这是我的尝试:
编辑:由于OP询问如何存储/检索多个记录,因此我决定更新原始代码。
那么,有什么变化吗?现在有一个数组student_t apprentice[3];
用于存储3名学生的信息。整个数组被序列化到磁盘上,然后全部加载回RAM,从而可以读取/搜索特定记录。请注意,这是一个非常非常小的文件(84字节)。我不建议在巨大的文件中搜索记录时使用此方法。
#include <fstream>
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
typedef struct student
{
char name[10];
int age;
vector<int> grades;
}student_t;
int main()
{
student_t apprentice[3];
strcpy(apprentice[0].name, "john");
apprentice[0].age = 21;
apprentice[0].grades.push_back(1);
apprentice[0].grades.push_back(3);
apprentice[0].grades.push_back(5);
strcpy(apprentice[1].name, "jerry");
apprentice[1].age = 22;
apprentice[1].grades.push_back(2);
apprentice[1].grades.push_back(4);
apprentice[1].grades.push_back(6);
strcpy(apprentice[2].name, "jimmy");
apprentice[2].age = 23;
apprentice[2].grades.push_back(8);
apprentice[2].grades.push_back(9);
apprentice[2].grades.push_back(10);
// Serializing struct to student.data
ofstream output_file("students.data", ios::binary);
output_file.write((char*)&apprentice, sizeof(apprentice));
output_file.close();
// Reading from it
ifstream input_file("students.data", ios::binary);
student_t master[3];
input_file.read((char*)&master, sizeof(master));
for (size_t idx = 0; idx < 3; idx++)
{
// If you wanted to search for specific records,
// you should do it here! if (idx == 2) ...
cout << "Record #" << idx << endl;
cout << "Name: " << master[idx].name << endl;
cout << "Age: " << master[idx].age << endl;
cout << "Grades: " << endl;
for (size_t i = 0; i < master[idx].grades.size(); i++)
cout << master[idx].grades[i] << " ";
cout << endl << endl;
}
return 0;
}
输出:
Record #0
Name: john
Age: 21
Grades:
1 3 5
Record #1
Name: jerry
Age: 22
Grades:
2 4 6
Record #2
Name: jimmy
Age: 23
Grades:
8 9 10
二进制文件的转储:
$ hexdump -c students.data
0000000 j o h n \0 237 { \0 � � { � 025 \0 \0 \0
0000010 ( � � \b 4 � � \b 8 � � \b j e r r
0000020 y \0 � \0 � � | \0 026 \0 \0 \0 @ � � \b
0000030 L � � \b P � � \b j i m m y \0 \0 \0
0000040 � 6 � \0 027 \0 \0 \0 X � � \b d � � \b
0000050 h � � \b
0000054
vector
确实是问题所在,它包含容量、计数和指向真实数据的指针。将该指针保存到磁盘上是没有意义的,您需要保存它所指向的数据。Jerry的答案解释了一个很好的方法来做到这一点。 - Ben Voigtstd::vector
进行序列化是完全无意义的,所以被踩了。 - Daniel Jour通常,你可以通过先写入向量的长度,然后写入该数量的元素来序列化一个向量。当你读取它时,首先读取长度可以让你知道需要读取多少个元素作为该向量的一部分。作为一个简单的第一步近似,可以考虑以下内容:
template<class T>
std::ostream &operator<<(std::ostream &output, T const &input) {
T::size_type size = input.size();
output << size << "\n";
std::copy(input.begin(), input.end(),
std::ostream_iterator<T::value_type>(output, "\n"));
return output;
}
template<class T>
std::istream &operator>>(std::istream &input, T &output) {
T::size_type size, i;
input >> size;
output.resize(size);
std::copy_n(
std::istream_iterator<t::value_type>(input),
size,
output.begin());
return input;
}
此外,它以文本格式序列化,每行一个数字。关于文本与二进制比较的讨论已经发生过,因此我不会在这里重复所有的论点 -- 我只想指出,同样的基本思想可以在二进制格式下同样有效地实现。
std::istream_iterator<T::value_type>(input),
(尝试编辑和修复,但无法接受。) - jmcarter9t