将结构从二进制文件读取到链表,导致无限循环

Reading structure from Binary file to Linked List leading to an infinite loop

本文关键字:无限循环 链表 结构 二进制文件 读取      更新时间:2023-10-16

这就是我的结构构建的方式

struct dNascimento{
int day, month, year;
};
struct morada{
string street;
int doorNum;
string postCode;
};
typedef struct student{
unsigned int id; //Número mecanográfico
string name;
string password;
morada addressStudent;
string course;
dNascimento birth;
int money;
student* next;
}* studentPointer;

我正在通过这个功能将学生记录添加到链接列表中

void addStudent(studentPointer studentToAdd) {
studentToAdd->next = NULL;
if (head != NULL) {
current = head;
while (current->next != NULL)
current = current->next;
current->next = studentToAdd;

}
else
head = studentToAdd;
}

这是我用来将链接列表中的学生保存到二进制文件的功能

void saveStudentsToFile() {
FILE *file = fopen("records.bin", "wb");
if (file != NULL) {
if (head != NULL) {
current = head;
int numberOfStudents = 0;
while (current != NULL){
if (fwrite(current, sizeof(student), 1, file) != 1)
cout << "nt> Erro ao guardar o aluno " << current->name << " no ficheiro!n" << endl;
current = current->next;
numberOfStudents++;
};
cout << "nt> " << numberOfStudents << " aluno(s) guardados com sucesso!n" << endl;
//^ Number of students saved successfully
fclose(file);
}else
cout << "nt> Não há registos de alunos para guardar!n" << endl;
//^ There are no students to save to the file
}else
cout << "nt> Erro ao abrir o ficheiro para guardar registo de alunos!n" << endl;
//^ Error opening file to save students
}

这是我用来将学生从文件中保存到链接列表的方法

void loadFile() {
FILE *file = fopen("records.bin", "rb");
if (file != NULL) {
studentPointer studentReader = new student;
studentReader = (studentPointer) malloc(sizeof(student));
int numberOfStudentsLoaded = 0;
while (!(fread(studentReader, sizeof(student), 1, file) != 1)){
addStudent(studentReader);
numberOfStudentsLoaded++;
};
fclose(file);
cout << "nt> " << numberOfStudentsLoaded << " aluno(s) carregado(s) com sucesso!n" << endl;
//^ Number of students loaded successfully
}
else
cout << "nt> Erro ao abrir o ficheiro dos registos!n" << endl;
//^ Error opening file to load records
}

这是我在链接列表中列出学生的方法

void listStudents() {
if (head != NULL) {
current = head;
while (current != NULL) {
cout << "nt> ID #" << current->id << endl;
cout << "t> " << current->name << endl;
cout << "t> " << current->password << endl;
current = current->next;
};
}
else
cout << "nt> Não tem registos guardados!n" << endl;
//^ No records saved to display
}

当我手动将记录添加到链表中并使用listStudents()显示它们时,它们会完美显示,但当我将学生记录保存到二进制文件并加载它们时,listStudents()方法会进行无限循环,只显示保存在二进制文件中的最后一条记录。

请记住,结构中的每个变量在保存之前都已正确初始化。

当我手动插入学生时,他们如何通过listStudents()显示http://image.prntscr.com/image/73459c40d81d462ca043ee414d1556d0.png

学生在IsaveStudentsToFile()loadFile()之后的表现http://image.prntscr.com/image/c3dfb61235de46b7adb757d0762883a9.png

代码的问题之一是无法使用fread从文件中读取student数据(fwrite也是如此)。您的学生类不是POD(纯旧数据),它包含string变量,这些变量无法通过使用fread从二进制文件中读取来初始化。您应该使用fstream逐字段写入输出文件,然后逐字段读取。或者将您的学生结构转换为POD,即:用char name[64];替换所有string name;

此外,如果存储:student* next;,则不应使用其值,地址将无效。

您的代码看起来更像C而不是C++,例如:

为什么:

studentPointer studentReader = new student;
studentReader = (studentPointer) malloc(sizeof(student));

你不需要(studentPointer) malloc(sizeof(student));。此外,您不应该使用malloc,因为它不会调用string变量的构造函数。

最终,永无止境的循环可能是由代码中的未定义行为引起的。

[编辑]

无限循环的原因是,每次从文件中读取一个学生时,你们并没有进行分配,所以你们最终得到的都是相同的学生。以下是更正后的代码。:

int numberOfStudentsLoaded = 0;
while (true){
studentReader = (studentPointer) malloc(sizeof(student));
if ((fread(studentReader, sizeof(student), 1, file) != 1)
break;
addStudent(studentReader);
numberOfStudentsLoaded++;
};