如何显示根据 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>
是最简单的容器。
所以,我认为你的程序的整体流程应该是这样的:
- 阅读整个
student.dat
并将在那里找到的所有学生信息放入容器中,例如 std::vector<student>
。
- 对容器进行排序。
- 让用户通过修改
std::vector<student>
. 的成员来操作记录(创建、读取、更新、删除)
- 当用户想要退出时,将
std::vector<student>
的内容写回文件students.dat
(可能带有不保存退出的选项)。
在下一节中,建议 1 和 2 将回答您的问题,而建议 3 将说明您的程序的其余部分需要如何更改才能与前两个建议一起工作。
一些建议:
- 更容易从文件中加载学生。
为 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
人类可读吗?
- 创建一个比较函数
bool operator<(const student& A, const student& B)
用于排序。
如果 A
学生应该排在 B
学生之前,此函数应该 return 为真,否则为假。创建此方法后,您可以调用 std::sort(all_students.begin(), all_students.end())
以根据该比较函数中定义的标准对学生列表进行排序。 std::sort()
函数需要在每次修改学生列表后调用。
- 所有操作学生数据的函数都应该传递
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
传递。
要改进这个程序还有很多工作要做,但我认为这些建议应该能让你开始更有条理地思考。
这是我的全部代码 我想在使用主菜单中的选项 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>
是最简单的容器。
所以,我认为你的程序的整体流程应该是这样的:
- 阅读整个
student.dat
并将在那里找到的所有学生信息放入容器中,例如std::vector<student>
。 - 对容器进行排序。
- 让用户通过修改
std::vector<student>
. 的成员来操作记录(创建、读取、更新、删除)
- 当用户想要退出时,将
std::vector<student>
的内容写回文件students.dat
(可能带有不保存退出的选项)。
在下一节中,建议 1 和 2 将回答您的问题,而建议 3 将说明您的程序的其余部分需要如何更改才能与前两个建议一起工作。
一些建议:
- 更容易从文件中加载学生。
为 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
人类可读吗?
- 创建一个比较函数
bool operator<(const student& A, const student& B)
用于排序。
如果 A
学生应该排在 B
学生之前,此函数应该 return 为真,否则为假。创建此方法后,您可以调用 std::sort(all_students.begin(), all_students.end())
以根据该比较函数中定义的标准对学生列表进行排序。 std::sort()
函数需要在每次修改学生列表后调用。
- 所有操作学生数据的函数都应该传递
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
传递。
要改进这个程序还有很多工作要做,但我认为这些建议应该能让你开始更有条理地思考。