目录
推荐阅读:
?C/C++ 中用于动态内存分配的函数。
malloc 函数:malloc 函数用于在堆上分配指定大小的内存块。它接受一个参数,即所需内存块的字节数,返回一个指向分配内存的指针。如果分配失败,则返回 NULL。
calloc 函数:calloc 函数类似于 malloc 函数,但它还会将分配的内存块初始化为零。它接受两个参数,即所需内存块的个数和每个内存块的字节数。它返回一个指向分配内存的指针。如果分配失败,则返回 NULL。
realloc 函数:realloc 函数用于重新分配已分配内存的大小。它接受两个参数,即原始内存块的指针和新的内存块大小。如果内存分配成功,则返回一个指向新分配内存的指针。如果分配失败,则返回 NULL。同时,realloc 函数还会尝试保留原始内存块中的数据,将其复制到新分配的内存块中。
?
该系统可以添加、查询和删除学生信息,并将学生信息保存到文件中。
这个学生管理系统的设计包括了以下几个方面:
学生类(Student)的定义:包括学生的姓名、年龄、性别等信息,并提供了显示信息、从文件中读取信息、将信息写入文件等功能。
学生管理类(StudentManager)的定义:包括添加、查询和删除学生信息的功能,以及将学生信息保存到文件的功能。
在主函数中使用上述两个类来实现一个简单的学生管理系统:通过用户输入实现添加、查询和删除学生信息的功能,并将修改后的学生信息保存到文件中。
这个学生管理系统提供了基本的学生信息管理功能,并且通过文件输入输出流库实现了将信息保存到文件和从文件中读取信息的功能。同时,还提到了可以扩展该系统,增加成绩、课程表等功能。
此外,还介绍了C++类模板的概念,说明了类模板的定义以及使用类模板时的一些注意事项,强调了类模板的灵活性和通用性,以及它在提高代码复用性和可维护性方面的优势。
Student
类该类包含学生的姓名、年龄和性别信息,以及操作这些信息的成员函数。其中,为了方便操作,我们使用字符串表示学生的性别信息,1 表示男性,0 表示女性。
#include <iostream>
#include <fstream> // 文件输入输出流库
#include <vector>
class Student {
public:
// 默认构造函数
Student() {
name = "";
age = 0;
gender = "";
}
// 带参数的构造函数
Student(std::string n, int a, std::string g) {
name = n;
age = a;
gender = g;
}
// 成员函数,用于显示学生信息
void DisplayInfo() const {
std::cout << "姓名:" << name << "\t年龄:" << age << "\t性别:" << gender << std::endl;
}
// 成员函数,用于从文件中读取学生信息
void LoadFromFile(std::ifstream& file) {
file >> name >> age >> gender;
}
// 成员函数,用于将学生信息写入文件
void WriteToFile(std::ofstream& file) const {
file << name << " " << age << " " << gender << std::endl;
}
// getter 函数,用于获取学生姓名
std::string GetName() const {
return name;
}
private:
std::string name; // 姓名
int age; // 年龄
std::string gender; // 性别
};
StudentManager
类该类包含添加、查询和删除学生信息的成员函数,以及将学生信息保存到文件的成员函数。
class StudentManager {
public:
// 成员函数,用于添加学生信息
void AddStudent(const Student& s) {
students.push_back(s);
}
// 成员函数,用于查询学生信息
void QueryStudent(const std::string& name) const {
bool found = false;
for (const auto& s : students) {
if (s.GetName() == name) {
s.DisplayInfo();
found = true;
}
}
if (!found) {
std::cout << "未找到姓名为" << name << "的学生" << std::endl;
}
}
// 成员函数,用于删除学生信息
void DeleteStudent(const std::string& name) {
for (auto it = students.begin(); it != students.end(); ++it) {
if (it->GetName() == name) {
students.erase(it);
std::cout << "已删除姓名为" << name << "的学生" << std::endl;
return;
}
}
std::cout << "未找到姓名为" << name << "的学生" << std::endl;
}
// 成员函数,用于从文件中读取学生信息
void LoadFromFile(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "文件打开失败:" << filename << std::endl;
return;
}
Student s;
while (!file.eof()) {
s.LoadFromFile(file);
if (s.GetName() != "") { // 去除文件末尾多余空行
students.push_back(s);
}
}
file.close();
}
// 成员函数,用于将学生信息写入文件
void WriteToFile(const std::string& filename) const {
std::ofstream file(filename);
if (!file.is_open()) {
std::cerr << "文件打开失败:" << filename << std::endl;
return;
}
for (const auto& s : students) {
s.WriteToFile(file);
}
file.close();
}
private:
std::vector<Student> students; // 学生信息列表
};
main
函数中具体来说,程序首先从文件中读取学生信息,然后通过用户输入实现添加、查询和删除学生信息的功能,最后将修改后的学生信息保存到文件中。
int main() {
StudentManager manager;
manager.LoadFromFile("students.txt"); // 从文件中读取学生信息
int choice = 0;
while (true) {
std::cout << "1. 添加学生信息" << std::endl;
std::cout << "2. 查询学生信息" << std::endl;
std::cout << "3. 删除学生信息" << std::endl;
std::cout << "4. 退出程序" << std::endl;
std::cout << "请选择操作:";
std::cin >> choice;
if (choice == 1) { // 添加学生信息
std::string name, gender;
int age;
std::cout << "请输入学生姓名、年龄和性别(男/女):";
std::cin >> name >> age >> gender;
manager.AddStudent(Student(name, age, gender));
}
else if (choice == 2) { // 查询学生信息
std::string name;
std::cout << "请输入要查询的学生姓名:";
std::cin >> name;
manager.QueryStudent(name);
}
else if (choice == 3) { // 删除学生信息
std::string name;
std::cout << "请输入要删除的学生姓名:";
std::cin >> name;
manager.DeleteStudent(name);
}
else if (choice == 4) { // 保存并退出程序
manager.WriteToFile("students.txt");
break;
}
else {
std::cout << "无效的选项,请重新输入" << std::endl;
}
}
return 0;
}
最终,当用户选择退出程序时,程序会将修改后的学生信息保存到文件 students.txt
中。可以通过查看该文件来验证学生信息是否被正确地保存。
通过上面的代码实现,我们学习了如何使用 C++ 类来管理数据,以及如何使用文件输入输出流库将数据保存到文件中。这是一个简单的学生管理系统,但是可以扩展为更复杂的系统,例如添加成绩、课程表等功能。
#include <iostream>
#include <fstream> // 文件输入输出流库
#include <vector>
class Student {
public:
// 默认构造函数
Student() {
name = "";
age = 0;
gender = "";
}
// 带参数的构造函数
Student(std::string n, int a, std::string g) {
name = n;
age = a;
gender = g;
}
// 成员函数,用于显示学生信息
void DisplayInfo() const {
std::cout << "姓名:" << name << "\t年龄:" << age << "\t性别:" << gender << std::endl;
}
// 成员函数,用于从文件中读取学生信息
void LoadFromFile(std::ifstream& file) {
file >> name >> age >> gender;
}
// 成员函数,用于将学生信息写入文件
void WriteToFile(std::ofstream& file) const {
file << name << " " << age << " " << gender << std::endl;
}
// getter 函数,用于获取学生姓名
std::string GetName() const {
return name;
}
private:
std::string name; // 姓名
int age; // 年龄
std::string gender; // 性别
};
class StudentManager {
public:
// 成员函数,用于添加学生信息
void AddStudent(const Student& s) {
students.push_back(s);
}
// 成员函数,用于查询学生信息
void QueryStudent(const std::string& name) const {
bool found = false;
for (const auto& s : students) {
if (s.GetName() == name) {
s.DisplayInfo();
found = true;
}
}
if (!found) {
std::cout << "未找到姓名为" << name << "的学生" << std::endl;
}
}
// 成员函数,用于删除学生信息
void DeleteStudent(const std::string& name) {
for (auto it = students.begin(); it != students.end(); ++it) {
if (it->GetName() == name) {
students.erase(it);
std::cout << "已删除姓名为" << name << "的学生" << std::endl;
return;
}
}
std::cout << "未找到姓名为" << name << "的学生" << std::endl;
}
// 成员函数,用于从文件中读取学生信息
void LoadFromFile(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "文件打开失败:" << filename << std::endl;
return;
}
Student s;
while (!file.eof()) {
s.LoadFromFile(file);
if (s.GetName() != "") { // 去除文件末尾多余空行
students.push_back(s);
}
}
file.close();
}
// 成员函数,用于将学生信息写入文件
void WriteToFile(const std::string& filename) const {
std::ofstream file(filename);
if (!file.is_open()) {
std::cerr << "文件打开失败:" << filename << std::endl;
return;
}
for (const auto& s : students) {
s.WriteToFile(file);
}
file.close();
}
private:
std::vector<Student> students; // 学生信息列表
};
int main() {
StudentManager manager;
manager.LoadFromFile("students.txt"); // 从文件中读取学生信息
int choice = 0;
while (true) {
std::cout << "1. 添加学生信息" << std::endl;
std::cout << "2. 查询学生信息" << std::endl;
std::cout << "3. 删除学生信息" << std::endl;
std::cout << "4. 退出程序" << std::endl;
std::cout << "请选择操作:";
std::cin >> choice;
if (choice == 1) { // 添加学生信息
std::string name, gender;
int age;
std::cout << "请输入学生姓名、年龄和性别(男/女):";
std::cin >> name >> age >> gender;
manager.AddStudent(Student(name, age, gender));
}
else if (choice == 2) { // 查询学生信息
std::string name;
std::cout << "请输入要查询的学生姓名:";
std::cin >> name;
manager.QueryStudent(name);
}
else if (choice == 3) { // 删除学生信息
std::string name;
std::cout << "请输入要删除的学生姓名:";
std::cin >> name;
manager.DeleteStudent(name);
}
else if (choice == 4) { // 保存并退出程序
manager.WriteToFile("students.txt");
break;
}
else {
std::cout << "无效的选项,请重新输入" << std::endl;
}
}
return 0;
}
是一种通用的类定义,它允许我们编写一次代码,然后在需要时使用不同的类型参数进行实例化。通过使用类模板,可以提供一种灵活的方式来处理各种数据类型的需求。
类模板的定义以关键字template
开头,后面跟着一个或多个模板参数。模板参数可以是类型参数、非类型参数或模板参数包。通过在模板定义中使用这些参数,我们可以在使用类模板时指定不同的类型或值。
使用类模板时,我们需要提供具体的类型或值作为模板参数,以实例化一个特定的类。根据不同的模板参数,编译器会生成相应的类定义。这使得我们可以使用相同的代码来处理不同的数据类型,提高了代码的复用性和可维护性。
类模板可以用于定义一些通用的数据结构和算法,如容器类(例如向量、链表、队列等)和排序算法(例如快速排序、归并排序等)。通过使用类模板,我们可以在不同的场景中使用相同的逻辑,而无需为每种数据类型编写重复的代码。
总而言之,C++类模板提供了一种强大的机制,允许我们以通用的方式处理不同的数据类型。通过模板参数化,可以生成具体的类定义,以适应各种类型的需求。这样可以提高代码的复用性和可维护性,使我们能够更高效地开发和管理代码。