如何显示根据 C++ .dat 文件中的卷号排序的记录

how to display records sorted according to roll no in c++ .dat file

这是我的全部代码 我想在使用主菜单中的选项 2 显示所有学生时对记录进行排序 此代码返回我保存的数据意味着未排序。

#include<iostream>
#include<fstream>
#include<iomanip>
#include<vector>
using namespace std;



class student
{
    int Idnum;
    char Name[25];
    char Course[30];
    int Result;

public:
    void getdata();
    void showdata() const;
    void show_tabular() const;
    int getIDNum() const;
};

void student::getdata()
{
    cout << "\nEnter student's ID Number: ";//prints Enter student's ID Number
    cin >> Idnum;
    cout << "\n\nEnter student's Name: ";//prints Enter student's Name
    cin.ignore();//to ignore from the input buffer
    cin.getline(Name, 25);
    cout << "\nEnter student's Course: ";//prints Enter student's Course
    cin >> Course;
    cout << "\nEnter student's Result: ";//prints Enter student's Result
    cin >> Result;

}

void student::showdata() const
{
    cout << "\nID Number: " << Idnum;//prints ID Number
    cout << "\nName: " << Name;//prints Name
    cout << "\nCourse: " << Course;//prints Course
    cout << "\nResult: " << Result;//prints Result
}

void student::show_tabular() const
{
    cout << Idnum << setw(6) << " " << Name << setw(20) << Course << setw(20) << Result << setw(4) << endl;
}

int  student::getIDNum() const
{
    return Idnum;
}



void SaveStudent();
void displayAll();
void Searchdisplay(int);
void modifyStudent(int);
void deleteStudent(int);
void DisplayResult();

这是创建 student.dat 文件的代码,如果这里不存在,如果存在,则写入一个新的学生记录,但这不会按我想要的方式对记录进行排序。

void write_student()//to create students record
{
    student st;
    ofstream outFile;
    ifstream inFile;
    outFile.open("student.dat", ios::binary | ios::app);//opens file student.dat
    st.getdata();
    //cout << st.getIDNum();
    if (inFile.seekg(reinterpret_cast<char *> (&st)))
    {

    }
    outFile.write(reinterpret_cast<char *> (&st), sizeof(student));//writes the file
    outFile.close();//closes the file
    cout << "\n\nStudent record Has Been Created ";
    cin.ignore();
    cin.get();
}

这是我显示学生记录的地方,但这将显示未排序的记录,我希望它以排序方式表示按学生人数升序排列。

void display_all()//to display the student record
{
    student st;
    ifstream inFile;
    inFile.open("student.dat", ios::binary);//opens file student.dat
    if (!inFile)
    {
        cout << "File could not be open !! Press any Key...";
        cin.ignore();//to ignore from the input buffer
        cin.get();//to access the char
        return;
    }
    cout << "\n\n\n\t\tDISPLAY ALL RECORD !!!\n\n";

    while (inFile.read(reinterpret_cast<char *> (&st), sizeof(st)))
    {   
        st.showdata(); //function to show data on screen
        cout << "\n\n====================================\n";
    }
    inFile.close();//closes the file
    cin.ignore();
    cin.get();
}



void display_sp(int n)//to search for student record
{
    student st;
    ifstream inFile;
    inFile.open("student.dat", ios::binary);//opens file student.dat
    if (!inFile)
    {
        cout << "File could not be open !! Press any Key...";
        cin.ignore();
        cin.get();
        return;
    }
    bool flag = false;//for false condition
    while (inFile.read(reinterpret_cast<char *> (&st), sizeof(student)))
    {
        if (st.getIDNum() == n)
        {
            st.showdata();
            flag = true;
        }
    }
    inFile.close();//closes the file
    if (flag == false)
        cout << "\n\nrecord not exist";//prints record not exist
    cin.ignore();
    cin.get();
}


void modify_student(int n)//to modify the record
{
    bool found = false;//for false condition
    student st;
    fstream File;
    File.open("student.dat", ios::binary | ios::in | ios::out);//opens the file student.dat
    if (!File)
    {
        cout << "File could not be open !! Press any Key...";
        cin.ignore();
        cin.get();
        return;
    }
    while (!File.eof() && found == false)
    {

        File.read(reinterpret_cast<char *> (&st), sizeof(student));//reads the file
        if (st.getIDNum() == n)
        {
            st.showdata();
            cout << "\n\nPlease Enter The New Details of student" << endl;
            st.getdata();
            int pos = (-1)*static_cast<int>(sizeof(st));
            File.seekp(pos, ios::cur);
            File.write(reinterpret_cast<char *> (&st), sizeof(student));
            cout << "\n\n\t Record Updated";
            found = true;
        }
    }
    File.close();//closes the file
    if (found == false)
        cout << "\n\n Record Not Found ";
    cin.ignore();
    cin.get();
}



void delete_student(int n)//to delete the student record
{
    student st;
    ifstream inFile;
    inFile.open("student.dat", ios::binary);//opens the student.dat file
    if (!inFile)
    {
        cout << "File could not be open !! Press any Key...";
        cin.ignore();
        cin.get();
        return;
    }
    ofstream outFile;
    outFile.open("Temp.dat", ios::out);//to open another file
    inFile.seekg(0, ios::beg);
    while (inFile.read(reinterpret_cast<char *> (&st), sizeof(student)))
    {
        if (st.getIDNum() != n)
        {
            outFile.write(reinterpret_cast<char *> (&st), sizeof(student));
        }
    }
    outFile.close();//to open another file
    inFile.close();
    remove("student.dat");
    rename("Temp.dat", "student.dat");
    cout << "\n\n\tRecord Deleted ..";
    cin.ignore();
    cin.get();
}





int main()
{
    char ch;
    int num;
    cout.setf(ios::fixed | ios::showpoint);
    cout << setprecision(2);
    do
    {
        system("cls");
        cout << "\t===================================";
        cout << "\n\n\t1. CREATE STUDENT RECORD";
        cout << "\n\n\t2. DISPLAY ALL STUDENTS RECORDS";
        cout << "\n\n\t3. SEARCH STUDENT RECORD ";
        cout << "\n\n\t4. MODIFY STUDENT RECORD";
        cout << "\n\n\t5. DELETE STUDENT RECORD";
        cout << "\n\n\t6. EXIT";
        cout << "\n\n\t===================================";
        cout << "\n\n\tPlease Enter Your Choice (1-6): ";
        cin >> ch;
        system("cls");
        switch (ch)//uses switch casee
        {
        case '1':   write_student(); break;
        case '2':   display_all(); break;
        case '3':   cout << "\n\n\tPlease Enter Student's ID number: "; cin >> num;
            display_sp(num); break;
        case '4':   cout << "\n\n\tPlease Enter Student's ID number: "; cin >> num;
            modify_student(num); break;
        case '5':   cout << "\n\n\tPlease Enter Student's ID number: "; cin >> num;
            delete_student(num); break;
        case '6':   exit(0);;
        default:    cout << "\a";

        }
    } while (ch != '6');

    return 0;
}

按排序顺序显示学生的主要困难在于您的程序通过让每个函数读取文件并按顺序对每个学生记录进行操作来工作。只有当您将所有数据加载到您的程序中时,排序才会发生。为了显示排序的学生列表,您需要将所有学生记录加载到您的程序中,并将它们全部放在同一个容器中。 std::vector<student> 是最简单的容器。

所以,我认为你的程序的整体流程应该是这样的:

  1. 阅读整个 student.dat 并将在那里找到的所有学生信息放入容器中,例如 std::vector<student>
  2. 对容器进行排序。
  3. 让用户通过修改 std::vector<student>.
  4. 的成员来操作记录(创建、读取、更新、删除)
  5. 当用户想要退出时,将std::vector<student>的内容写回文件students.dat(可能带有不保存退出的选项)。

在下一节中,建议 1 和 2 将回答您的问题,而建议 3 将说明您的程序的其余部分需要如何更改才能与前两个建议一起工作。

一些建议:

  1. 更容易从文件中加载学生。

student class 创建一个以 std::ifstream& 作为参数的方法。这样,在打开文件后,您可以像这样加载所有学生数据:

int main()
{
    ifstream inFile("student.dat");
    std::vector<student> all_students;
    while(inFile)
    {
        student st;
        st.getData(inFile);
        all_students.push_back(st);
    }

    // continue with program
}

此方法与当前的 student::getData() 方法非常相似,但它会跳过文本提示。我还发现这种方式比您的 reinterpret_cast 代码更容易理解,这让我担心它的实际作用。您当前的代码 student.dat 人类可读吗?

  1. 创建一个比较函数bool operator<(const student& A, const student& B)用于排序。

如果 A 学生应该排在 B 学生之前,此函数应该 return 为真,否则为假。创建此方法后,您可以调用 std::sort(all_students.begin(), all_students.end()) 以根据该比较函数中定义的标准对学生列表进行排序。 std::sort() 函数需要在每次修改学生列表后调用。

  1. 所有操作学生数据的函数都应该传递 all_students 数据

通过专门编写的方法直接使用 student 数据比对文件流数据进行复杂的操作要容易得多。例如,如果您将 std::vector<student>& 传递给 modify_student() 函数,它将如下所示:

void modify_student(std::vector<student>& all_students, int n)//to modify the record
{
    for (auto& st : all_students)
    {
        if (st.getIDNum() == n)
        {
            st.showdata();
            cout << "\n\nPlease Enter The New Details of student" << endl;
            st.getdata();
            return;
        }
    }
    cout << "\n\n Record Not Found ";
}

如果您不使用 C++11 或更高版本,这等同于:

void modify_student(std::vector<student>& all_students, int n)//to modify the record
{
    for (size_t i = 0; i < all_students.size(); ++i)
    {
        student& st = all_students[i];
        if (st.getIDNum() == n)
        {
            st.showdata();
            cout << "\n\nPlease Enter The New Details of student" << endl;
            st.getdata();
            return;
        }
    }
    cout << "\n\n Record Not Found ";
}

这要简单得多,因为您没有文件遍历和用户 input/output 隐藏函数的实际逻辑。

如果一个函数只显示像 display_all() 这样的数据,那么您应该将 student 列表作为 const std::vector<student>& all_students 传递。


要改进这个程序还有很多工作要做,但我认为这些建议应该能让你开始更有条理地思考。