从 C++ 中读取文件时动态分配内存给结构
Posted
技术标签:
【中文标题】从 C++ 中读取文件时动态分配内存给结构【英文标题】:dynamically allocating memory to struct when reading from file in C++ 【发布时间】:2012-10-19 22:02:57 【问题描述】:我有一个结构
typedef struct student
char name[10];
int age;
vector<int> grades;
student_t;
我正在将其内容写入二进制文件。
我在不同的时间写入,文件中有很多数据是从这个结构写入的。
现在,我想将二进制文件中的所有数据读取到结构中。 我不确定如何(动态地)为结构分配内存,以便结构可以容纳结构上的所有数据。
你能帮我解决这个问题吗?
代码:
#include <fstream>
#include <iostream>
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <iterator>
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;
input_file.seekg (0, ios::end);
cout << input_file.tellg();
std::vector<student_t> s;
// input_file.read((char*)s, sizeof(s)); - dint work
/*input_file >> std::noskipws;
std::copy(istream_iterator(input_file), istream_iterator(), std::back_inserter(s));*/
while(input_file >> master) // throws error
s.push_back(master);
return 0;
【问题讨论】:
我不明白你的问题。vector
已经处理动态分配。你的意思是你有一个装满student_t
的容器要动态分配?
说我将一个结构数组说 student_t[5] 写入二进制文件并执行 4 次。我想将二进制文件中的数据提取到结构中。但是我不知道已经编写了多少这样的结构(因为用户可以编写任意数量的这样的结构数组)。我想知道一种将动态数据拉到结构上的方法。
你必须记录写了多少个结构体。
为什么在一个地方使用vector,但是(1)不使用vector来获取多个学生和(2)使用c风格的字符串而不是std::string
?我的意思是,我为了学习低级的东西而忽略了高级功能,但使用它们的一半似乎很愚蠢。
如果您关心的是二进制文件,您可以测试 EOF (=End Of File)。如果是关于代码的 C++ 部分,您应该使用vector<student_t>
。向量已经处理了动态分配,您可以在它们上调用.size()
。
【参考方案1】:
您应该使用vector<student_t>
而不是旧式数组。它将处理动态分配(使用push_back()
添加项目),您可以使用size()
方法获取其大小。
编辑: 对于文件读取,您可以执行以下操作:
ifstream myfile;
myfile.open(file_name);
if (myfile.is_open())
while (myfile)
string s;
getline(myfile, s);
// Do something with the line
// Push information into students vector
不要忘记添加二进制选项。
对于student_t
结构中的name
,将其声明为string
会容易得多。这样,您就不必使用strcpy
之类的了,您只需输入mystudent.name = "jimmy"
【讨论】:
我试过这样做 while(input_file >> master) s.push_back(master);但我在 while 部分遇到错误。你能帮帮我吗? 您能否编辑您的问题以添加您刚刚尝试过的代码?不看代码很难提供帮助。 非常感谢您的解决方案。 我正在尝试。我仍然有一些问题。 好!如果您在我们的帮助下解决了问题,请不要忘记接受答案。【参考方案2】:您需要为此发明一种文件格式。在文件的开头,您将存储一个所谓的“标题”,其中包含有关其中包含的数据的信息。例如:
2 13 <DATA> 8 <DATA>
第一个数字 (2) 给出了存储在文件中的结构的数量。然后是数据块。每个数据块都以一个数字开头,该数字指定grades
向量的大小(第一个结构为 13,第二个结构为 8)。
在这种情况下,您从文件的开头读取一个 int。现在您知道该文件中保存了 2 个结构。然后,您阅读下一个 int,在本例中为 13。这告诉您您需要一个容量为 13 的向量。您可以创建一个,然后读取所有值。您将知道何时停止,因为您知道此结构中有多少数据:10 个字符(姓名)、1 个整数(年龄)、13 个整数(等级)。阅读完所有内容后,您就知道下一个 int 将成为文件中下一个结构的一部分。它将是数字 8,它告诉您下一个结构需要容量为 8 的向量。
等等,直到你读完所有内容。
请注意,这种二进制文件 I/O 方法不可移植。有两个原因。首先, int 的大小可能因平台而异。其次,int(和其他大于单个字节的数据)以二进制形式存储的方式也可能不同,即使它们具有相同的大小(请参阅http://en.wikipedia.org/wiki/Endianness 以获得解释。)但是如果您不打算使用您的程序和它生成的文件无论如何都是可移植的,那么我上面描述的方法就足够了。
【讨论】:
【参考方案3】:最直接的方法是解包向量,这样您写入文件的不是向量,而是一个整数数组以及数组中的整数个数。
因此,第一遍将是编写具有标准、不变结构的第一部分,然后是一个数字,表示将跟随的整数数量,然后最后遍历将整数写入文件的向量。
然后,当您读取文件时,您将使用空向量创建结构,将结构化且不变的第一部分读取到结构中,然后读取要放置在向量中的整数数量,然后读取文件中的整数数。当您从文件中读取整数时,您会将它们添加到结构中的向量中。
【讨论】:
实际上我没有任何问题将数据拉入向量中。如果我知道我想提取 3 组结构数据,那么我可以将其分配为 student_t s[3]。但在这里我不知道它是否为 3(它可以是基于文件内容的任意值)。我不知道该怎么做。你能帮我解决这个问题吗? 听起来你要么想要动态数组,比如student_t* s = new student_t[num_structs];
,要么是你的结构的vector
,比如std::vector<student_t> s;
。
@user1420351,您将需要使用集合类之一(例如vector)来动态添加从文件中读取的结构的副本。或者您可以按照 Geoff 建议的方式使用新的但是要这样做,您需要知道文件中有多少个,所以可能像 vector 这样的集合会更可取。以上是关于从 C++ 中读取文件时动态分配内存给结构的主要内容,如果未能解决你的问题,请参考以下文章