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

时间:2016-05-30 19:29:16

标签: c++

这是我的结构构建方式

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 << "\n\t> Erro ao guardar o aluno " << current->name << " no ficheiro!\n" << endl;

                current = current->next;
                numberOfStudents++;

            };

            cout << "\n\t> " << numberOfStudents << " aluno(s) guardados com sucesso!\n" << endl;
            //^ Number of students saved successfully
            fclose(file);

        }else
            cout << "\n\t> Não há registos de alunos para guardar!\n" << endl;
            //^ There are no students to save to the file
    }else
        cout << "\n\t> 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 << "\n\t> " << numberOfStudentsLoaded << " aluno(s) carregado(s) com sucesso!\n" << endl;
        //^ Number of students loaded successfully
    }
    else
        cout << "\n\t> 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 << "\n\t> ID #" << current->id << endl;
            cout << "\t> " << current->name << endl;
            cout << "\t> " << current->password << endl;
            current = current->next;
        };

    }
    else
        cout << "\n\t> Não tem registos guardados!\n" << endl;
        //^ No records saved to display
}

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

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

  

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

     

学生saveStudentsToFile()loadFile()之后如何出现   http://image.prntscr.com/image/c3dfb61235de46b7adb757d0762883a9.png

1 个答案:

答案 0 :(得分:0)

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

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

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

为什么:

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

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

最后,永无止境的循环可能是由代码中的Undefined Behaviors引起的。

[编辑]

无限循环的原因是因为每次从文件中读取学生时都不会分配,所以最终会得到所有相同的学生。以下是更正后的代码。:

    int numberOfStudentsLoaded = 0;
    while (true){
            studentReader = (studentPointer) malloc(sizeof(student));

            if ((fread(studentReader, sizeof(student), 1, file) != 1)
               break;

            addStudent(studentReader);
            numberOfStudentsLoaded++;
    };