从二进制文件C ++中读取动态内存分配字符串(char *)

时间:2014-05-29 15:14:04

标签: c++ memory-management binaryfiles

我正在尝试通过以下类型创建学生数据库:(班级学生)

class Student {           
    unsigned Id;//ID number
    char* name;// dynamic memory allocated name (size: 10)
    char* family;// dynamic memory allocated last name (size: 10)
    int gen;//gender
    unsigned MiddleTestGrade;// grade of the student in the middle test
    unsigned FinalTestGrade;// grade of the student in the final test
    double TotalGrade;// total grade of the student calculates automaticly (dont need to insert this as input)
};

我使用以下命令将所有这些信息写入二进制文件:( StudentData类型是上面提到的Student类)

file.write(reinterpret_cast<const char*>(&StudentData),sizeof(Student));

当我使用read命令从文件中获取所有数据时:

file.read(reinterpret_cast<char*>(&StudentData),sizeof (Student));

结果是除了动态分配的名称之外,一切都很好。它们只包含我写入文件的姓氏。

例如,在我将2名学生插入文件后:

  

12 Jhon Sna 1 95 100

  

77 David Gen 1 80 85

阅读和打印的结果将是:

  

12 David Gen 1 95 100

  

77 David Gen 1 80 85

当我使用字符串(不是动态分配)时,一切都应该如下:\

我做错了什么?

1 个答案:

答案 0 :(得分:1)

如果在struct中动态分配数据,则无法使用

file.write(reinterpret_cast<const char*>(&StudentData),sizeof(Student));

将所有数据写入文件中。这只会将结构中指针的二进制值写入文件。当您还原它们时,您将只恢复二进制值,这将导致不可预测的行为。

当有动态分配的数据并适当地读取它们时,您需要分别编写struct的每个字段。

编写Student的代码:

// Write Id
file.write(reinterpret_cast<const char*>(&(StudentData.Id)), sizeof(StudentData.Id));

// Get the length of name
// Write the length and then the name
size_t len = strlen(StudentData,name);
file.write(reinterpret_cast<const char*>(&len), sizeof(len));
file.write(StudentData.name, len);

// Get the length of family
// Write the length and then the family
len = strlen(StudentData,family);
file.write(reinterpret_cast<const char*>(&len), sizeof(len));
file.write(StudentData.family, len);

// Write the rest of the data
file.write(reinterpret_cast<const char*>(&(StudentData.gen)), sizeof(StudentData.gen);
file.write(reinterpret_cast<const char*>(&(StudentData.MiddleTestGrade)), sizeof(StudentData.MiddleTestGrade));
file.write(reinterpret_cast<const char*>(&(StudentData.FinalTestGrade)), sizeof(StudentData.FinalTestGrade));
file.write(reinterpret_cast<const char*>(&(StudentData.TotalGrade)), sizeof(StudentData.TotalGrade));

您必须一次读回一个字段的数据,并根据需要分配内存。

// Read the Id.
file.read(reinterpret_cast<char*>(&StudentData.Id),sizeof (Student.Id));

// Read length of the name
size_t len;
file.read(reinterpret_cast<char*>(&len), sizeof (len));

// Allocate memory for name.
Student.name = new char[len+1];

// Read the name and null-terminate it.
file.read(Student.name, len);
Student.name[len] = '\0';

// Read length of the family
file.read(reinterpret_cast<char*>(&len), sizeof (len));

// Allocate memory for family.
Student.family= new char[len+1];

// Read the family and null-terminate it.
file.read(Student.family, len);
Student.family[len] = '\0';

// Read the rest of the Student data
file.read(reinterpret_cast<char*>(&StudentData.gen),sizeof (Student.gen));
file.read(reinterpret_cast<char*>(&StudentData.MiddleTestGrade),sizeof (Student.MiddleTestGrade));
file.read(reinterpret_cast<char*>(&StudentData.FinalTestGrade),sizeof (Student.FinalTestGrade));
file.read(reinterpret_cast<char*>(&StudentData.TotalGrade),sizeof (Student.TotalGrade));