学生管理系统(C++)

引言

学习c++后一直想写个学生管理系统,趁假期花了一天终于肝出了完整代码,让我对c++的理解更深了一层;写代码时真正体会到了内存操作的困难(想学java),但是还是通过几个巧妙的方法解决了内存问题,并在n次debug后终于调试出了完整代码,接下来我来介绍一下整个系统;
整个系统面向的对象是学生,所以就先写了一个学生类,并赋予了基本属性:学号,姓名,班级职责,还有显示个人信息的一个行为,又把学生分为三部分,普通学生班干部班长,当然这三类都具有学生的特性,所以我们可以通过继承学生类来获得相同的属性和行为;
想好了对象就要想一下具体实现的功能,该系统分为七大功能,分别是:

0.退出管理程序
1.增加学生信息
2.显示学生信息
3.删除学生信息
4.修改学生信息
5.查找学生信息
6.清空所有数据

为了实现这些功能,设计了一个管理员类StudentManager,将这些行为封装在一起,然后依次实现就行了;
这时就需要考虑一些细节了,在增加学生信息时,我们该如何增加呢?我在StudentManager这个类中增添了一个属性,一个vector的容器来存放增加的学生,这时就有问题了,学生既然分成了三大类,我们并不知道每次到底增加的是哪一类学生,那么vector到底该定位存放哪种学生类型呢?
这时面向对象三大特性之一的多态的优势就显现了出来,因为普通学生班干部班长这三类已经继承了学生类,所以我们只需要将学生类写为抽象类即可(把显示个人信息函数showinfo写为纯虚函数),这样我们vector容器只需要记录学生类的指针,通过多态的特性就可以实现同时存放普通学生班干部班长这三类的指针了;

构思完成后就可以写代码了,在写的过程中也遇到过很多问题,说几个主要的
1,因为我想要将学生信息每次更新后都可以存放到文件中,所以我不仅仅需要写一个save保存函数,还需要一个文件初始化函数init_std,因为一旦这次的代码运行成功后,学生信息就会存放到文件中,但是下一次运行就会将这次的学生信息覆盖,于是我们只要在程序开始运行时文件存在的情况下调用这个init函数,将文件原本的信息先读取到并存放到vector中,就可以实现对上一次信息的保存;这里都是些空间分配的问题,都是小细节,就不提了(闹心)
2,这个代码中的几个地方我一直避免使用delete释放内存,因为一旦delete就会出现一个warning警告,因为数据存放到了堆区,我猜测是抽象类Student和继承它的子类析构函数的问题,所以我先在Student中加了一个纯虚析构函数,又分别在下面几个类中重写了析构函数,虽然解决了warning,但是代码一走到delete就无法正常运行了;但是在最后还要清空所有数据,这当然包括分配的内存空间,还有什么办法?我突然想到了vector容器有一个swap函数,这个函数功能是交换两个vector容器的内容,但是我们可以用它的特点压缩内存,当然这需要用一个巧妙的方法实现,感兴趣的可以了解一下,我是在clean中使用了该功能

vector<Student*>(*this -> m_StdArray).swap(*this -> m_StdArray);

完成了内存的释放;
3,其他的问题还有很多,但是现在看来都也没有什么大不了的,只要在写代码时能够细心点,一定要可以熟练度的使用指针,在代码中我通过vector来存放增加的学生,这个相当于一个二级指针数组,所以再空间分配和调用时多多少少出现了很多小问题,浪费了我很多时间,尤其是加上this指针后,我很多时候就是蒙圈状态,但是最后还是调试出来了😊;

总结:

这是我第一次写这种对我来说稍稍大点的项目,让我感触最深的就是在完成整个代码中需要统筹全局,定义的每一个类都需要恰到好处,类与类之间的联系都需要严谨考虑,代码的每个函数都是非常好写的,但是又该如何整合起来?函数之间又有什么样的联系?每个函数又该放到哪个位置?我需要多定义那些变量?这些都是需要我考虑的;这比平时做题所需要考虑的方面多了好多好多,尤其是面向对象编程中封装起来就是一个整体,所以需要更全面的考虑和数次的调试;还有对内存的操控也更加困难,这就需要扎实的基本功了;我不能保证现在我代码的完美,但是对我来说这是一次非常好的历练,当然如果有代码方面的问题也欢迎在评论区提出来。

注:我是在vscode上编译运行的,所有功能正常,但是在dev上部分功能就会出现问题,所以要注意下编译环境;

代码如下:

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

#define FILENAME "stdFILE.txt" //定义生成文件名称

//学生类(抽象类)
class Student {
public:
    virtual void showInfo() = 0; //显示个人信息
   // virtual ~Student() = 0;      //定义纯虚析构函数保证释放堆区内存时不会发生内存泄漏

    string StId;     //学号
    string m_name;  //姓名
    string m_Dept;  //职责
};
//普通学生类
class Nomalstuden : public Student {
public:
    Nomalstuden(string Id, string name, string dep);
    void showInfo(); //显示个人信息
    // ~Nomalstuden() {
    //     delete this;
    // }
};
//班长类
class ClassPresident : public Student {
public: 
    ClassPresident(string Id, string name, string dep);
    void showInfo ();
    // ~ClassPresident() {
    //     delete this;
    // }
};
//班干部类
class Classleader : public Student {
public: 
    Classleader(string Id, string name, string dep);
    void showInfo ();
    // ~Classleader() {
    //     delete this;
    // }
};

//管理员类
class StudentManager {
public:
    StudentManager();//构造函数
    void Show_Menu(); //打印菜单界面
    void Exit_System();//退出系统
    void Addinfo();    //增加学生信息
    void save();       //将学生信息保存到文件中
    void init_Std();   //初始化学生
    void show_Std();   //显示学生信息
    void del_Std();    //删除学生信息
    void mod_Std();    //修改学生信息
    void find_Std();   //查找学生信息
    void clean_File(); //清空文件
    int IsExist(string id);     //判断学号为id的学生信息是否存在,并返回该学生下标
    ~StudentManager();//析构函数

    vector<Student*> *m_StdArray; //存放增加的学生信息
    bool m_fileIsEmpty;     //标记文件是否为空
};

//学生类纯虚析构的外部实现
// Student :: ~Student() {
//     delete this;
// }

//管理员函数实现
StudentManager :: StudentManager() {
    ifstream ifs;
    ifs.open(FILENAME, ios :: in);
    //如果文件不存在
    if (!ifs.is_open()) {
        cout << "该文件不存在!" << endl;
        this -> m_fileIsEmpty = true;
        this -> m_StdArray = NULL;
        ifs.close();
        return ;
    }
    //文件存在但是数据为空
    char ch;  
    ifs >> ch;       //先读取一个字符
    if (ifs.eof()) {
        cout << "该文件为空!" <<endl;
        this -> m_fileIsEmpty = true;
        this -> m_StdArray = NULL;
        ifs.close();
        return ;
    }
    //文件存在,并记录初始数据
    this -> m_StdArray = new vector<Student*>;
    this -> init_Std();
}
void StudentManager :: Show_Menu() {
    cout << "-------------------------------------------" << endl;
	cout << "------------  欢迎使用学生管理系统! ----------" << endl;
	cout << "-------------  0.退出管理程序  -------------" << endl;
	cout << "-------------  1.增加学生信息  -------------" << endl;
	cout << "-------------  2.显示学生信息  -------------" << endl;
	cout << "-------------  3.删除学生信息  -------------" << endl;
	cout << "-------------  4.修改学生信息  -------------" << endl;
	cout << "-------------  5.查找学生信息  -------------" << endl;
	cout << "-------------  6.清空所有数据  -------------" << endl;
	cout << "-------------------------------------------" << endl;
	cout << endl;
}
void StudentManager :: Exit_System() {
    cout << "感谢您的使用!" << endl;
   // system("pause");
    exit(-1);  //退出系统
}
void StudentManager :: Addinfo() {
    if (!this -> m_StdArray)
    this -> m_StdArray = new vector<Student*>;
    cout << "学生信息开始录入" << endl;
    int i = 1; 
    while(true) {
        char flag;  
        string id;
        string name;
        string dep;
        cout << "请输入第" << i << "个学生学号:" << endl;
        cin >> id;
        cout << "请输入第" << i << "个学生姓名:" << endl;
        cin >> name;
        cout << "请输入第" << i << "个学生职位:(班长or班干部or普通学生)" << endl;
        cin >> dep;
        Student *std = NULL;
        if (dep == "班长") {
            std = new ClassPresident(id, name, dep);
        }
        else if (dep == "班干部") {
            std = new Classleader(id, name, dep);
        }
        else if (dep == "普通学生") {
            std = new Nomalstuden(id, name, dep);
        }
        else {
            cout << "该学生职位不存在!信息录入结束!" <<endl;
            break;
        }
        this -> m_StdArray -> push_back(std);
        i++;
        this -> m_fileIsEmpty = false;   //更新文件非空标记
        cout << "是否继续录入信息?(y继续录入,n结束录入)" <<endl;
        cin >> flag;
        if (flag == 'y') continue;
        else break;
    }
    cout << "成功添加了" << i - 1 << "名学生信息!" <<endl;
    this -> save();
    system("pause");
    system("cls");
}
void StudentManager :: save() {
    ofstream ofs;
    ofs.open(FILENAME, ios :: out);
    for (int i = 0; i < this -> m_StdArray -> size(); ++i) {
        ofs << this -> m_StdArray -> at(i) -> StId << " "
            << this -> m_StdArray -> at(i) -> m_name << " "
            << this -> m_StdArray -> at(i) -> m_Dept << endl;
    }
    ofs.close();
}
void StudentManager :: init_Std() {
    ifstream ifs;
    ifs.open(FILENAME, ios :: in);
    string id;
    string name;
    string dep;
    while (ifs >> id && ifs >> name && ifs >> dep) {
        Student * std = NULL;
        if (dep == "班长") {
            std = new ClassPresident(id, name, dep);
        }
        else if (dep == "班干部") {
            std = new Classleader(id, name, dep);
        }
        else if (dep == "普通学生") {
            std = new Nomalstuden(id, name, dep);
        }
        this -> m_StdArray -> push_back(std);
    }
    this -> save();
}
void StudentManager :: show_Std() {
    if (this -> m_fileIsEmpty) {
        cout << "文件不存在或者文件为空!" <<endl;
    }
    else {
        for (int i = 0; i < this -> m_StdArray -> size(); ++i) {
            this -> m_StdArray -> at(i) -> showInfo();
        }
    }
    system("pause");
    system("cls");
}
void StudentManager :: del_Std() {
    if (this -> m_fileIsEmpty) {
        cout << "文件不存在或者文件为空!" << endl;
    }
    else {
        cout << "请输入需要删除的学生学号:" << endl;
        string id;
        cin >>id;
        int index = this -> IsExist(id);
        if (index != -1) {
            this -> m_StdArray -> erase(this -> m_StdArray -> begin() + index);
            this -> save();
            cout << "删除成功!" <<endl;
        }
        else {
            cout << "删除失败,不存在该学号的学生!" <<endl;
        }
    }
    system("pause");
}
int StudentManager :: IsExist(string id) {
    int len = this -> m_StdArray -> size();
    int index = -1;
    for (int i = 0; i < len; ++i) {
        if (this -> m_StdArray -> at(i) -> StId == id) {
            index = i;
            break;
        }
    }
    return index;
}
void StudentManager :: mod_Std() {
    if (this -> m_fileIsEmpty) {
        cout << "文件不存在或者文件为空" <<endl;
    }
    else {
        cout << "请输入需要修改的学生学号:" << endl;
        string id;
        cin >> id;
        int index = this -> IsExist(id);
        if (index != -1) {
            //delete this -> m_StdArray -> at(index);
            string newid;
            string newname;
            string newdep;
            Student *std = NULL;
            cout<< "搜索到学号为" << id << "的学生,请输入新学号:" << endl;
            cin >> newid; 
            cout << "请输入新姓名:" <<endl;
            cin >> newname;
            cout << "请输入新职责:" <<endl;
            cin >> newdep;
            if (newdep == "班长") {
                std = new ClassPresident(newid, newname, newdep);
            }
            else if (newdep == "班干部") {
                std = new Classleader(newid, newname, newdep);
            }
            else if (newdep == "普通学生") {
                std = new Nomalstuden(newid, newname, newdep);
            }
            this -> m_StdArray -> at(index) = std;
            cout <<"修改成功!" << endl;
            this -> save();
        }
        else {
            cout << "修改失败,不存在该学号的学生!" << endl;
        }
    }
    system("pause");
}
void StudentManager :: find_Std() {
    if (this -> m_fileIsEmpty) {
        cout << "文件不存在或者文件为空" <<endl;
    }
    else {
        cout << "请输入需要查找的学生学号:" << endl;
        string id;
        cin >> id;
        int index = this -> IsExist(id);
        if (index != -1) {
            cout<< "查找成功!该学生信息如下:" << endl;
            this -> m_StdArray -> at(index) ->showInfo();
        }
        else {
            cout << "查找失败!该学生不存在!" <<endl;
        }
    }    
}
void StudentManager :: clean_File() {
    cout << "确定清空所有数据?" << endl;
    cout << "1,确定" <<endl;
    cout << "2,返回" <<endl;
    int selet = 0;
    cin >> selet;
    if (selet == 1) {
        ofstream ofs(FILENAME, ios :: trunc);
        ofs.close();
        if (this -> m_StdArray) {
            this -> m_StdArray -> clear();
            vector<Student*>(*this -> m_StdArray).swap(*this -> m_StdArray);
            this -> m_fileIsEmpty = true;
            this -> m_StdArray = NULL;
        }
        cout << "清空成功!" << endl;
    }
    system("pause");
    system("cls");
}
StudentManager :: ~StudentManager() {
    if (this -> m_StdArray) {
        this -> m_StdArray -> clear();
        delete[] this -> m_StdArray;
        this -> m_StdArray = NULL;
    }
}

//普通学生函数实现
Nomalstuden :: Nomalstuden(string Id, string name, string dep) {
    this -> StId = Id;
    this -> m_name = name;
    this -> m_Dept = dep;
}
void Nomalstuden :: showInfo() {
    cout << "学生学号:" << this -> StId
    << "\t学生姓名:" << this -> m_name
    << "\t学生职位:" << this -> m_Dept
    << "\t学生任务:遵守班级纪律" << endl; 
}

//班长函数实现
ClassPresident :: ClassPresident(string Id, string name, string dep) {
    this -> StId = Id;
    this -> m_name = name;
    this -> m_Dept = dep;
}
void ClassPresident :: showInfo () {
    cout << "学生学号:" << this -> StId
    << "\t学生姓名:" << this -> m_name
    << "\t学生职位:" << this -> m_Dept
    << "\t学生任务:管理班干部,与辅导员对接,带领班级" << endl;
}

//班干部函数实现
Classleader :: Classleader(string Id, string name, string dep) {
    this -> StId = Id;
    this -> m_name = name;
    this -> m_Dept = dep;
}
void Classleader :: showInfo () {
    cout << "学生学号:" << this -> StId
    << "\t学生姓名:" << this -> m_name
    << "\t学生职位:" << this -> m_Dept
    << "\t学生任务:履行自己的职责,和各科老师对接,管理班级学生" << endl;
}

//主函数
int main() {
    StudentManager stm;     //实例化管理员
    int choice;             //存储用户选项
    while(true) {
        stm.Show_Menu();    //调用打印界面成员函数
        cout << "请输入您的选择:" << endl;
        cin >> choice;
        switch (choice)
        {
        case 0:             //退出系统
            stm.Exit_System();
            break;
        case 1:             //增加学生
            stm.Addinfo();
            break;
        case 2:             //显示学生
            stm.show_Std();
            break;
        case 3:             //删除学生
            stm.del_Std();
            break;
        case 4:             //修改学生
            stm.mod_Std();
            break;
        case 5:             //查找学生
            stm.find_Std();
            break;
        case 6:             //清空文档
            stm.clean_File();
            break;   
        default:
            system("cls");  //清屏操作
            break;
        }
    }
    
    system("pause");
    return 0;
}
相当不错的一个成绩管理系统 #include #include #include #include using namespace std; enum {SUBJECT=5};//一共五门 typedef struct { char subject[10];//科目名称 int score;//科目成绩 }markinfo; typedef struct studentnode { markinfo mark[SUBJECT]; int totalmark; char name[10];//学生姓名 studentnode * next; }studentnode; class student { studentnode * head; public: student(); int addstudent(); ~student(); int countmark(); int sortbymark(); int save(); int show(); int display(); int readfiletolist(); int searchbyname(); }; student::student() //用构造函数来初始化。 { head=new studentnode; head->next=NULL; } //1.输入学生姓名、成绩等数据,并保存在链表中。 int student::addstudent() { studentnode * p; int i; char check; system("cls"); cout<<"**********************"<<endl; cout<<"请输入学生信息:"<<endl; do { p=new studentnode; cin.ignore(); cout<name); i=0; p->totalmark=0; do { cout<mark[i].subject); cout<>p->mark[i].score; } while(p->mark[i].score>100||p->mark[i].scoretotalmark=p->totalmark+p->mark[i].score; getchar(); } while(++i!=SUBJECT); if(head->next==NULL) { head->next=p;p->next=NULL; } else { p->next=head->next; head->next=p; } cout<next; if(p==NULL) { cout<<"没有学生,请重新输入"<<endl;system("pause");return 0; } else { cout<<"***************"<<endl; cout<<"学生成绩汇总:"<<endl; while(p) { cout<<"姓名:"<name<<" 总成绩:"<totalmark<next; } } system("pause"); return 0; } //4.输出所有学生成绩到一个文件中。 int student::save() { char address[35]; int i; studentnode * p=head->next; cout<<"请输入保存的地址"<<endl; cin.ignore(); gets(address); ofstream fout; fout.open(address,ios::app|ios::out); while(p) { fout<<"*"; fout<name<<"*"; i=0; while(i!=SUBJECT) { fout<mark[i].subject<<"*"; fout<mark[i].score; i++; } //fout<next; } fout.flush(); fout.close(); cout<next; while(p) { s=p->next; delete p; p=s; } delete head; } //3.按照总成绩大小对记录进行排序 int student::sortbymark() { studentnode *move1=head->next; studentnode *move2,*max,*pre1,*pre2,*maxpre,*s=move1; if(head->next==NULL) { cout<<"没有记录,请添加"<next!=NULL;pre1=move1,maxpre=pre1,move1=move1->next,max=move1) { for(pre2=move1,move2=move1->next;move2!=NULL;pre2=move2,move2=move2->next) if(move2->totalmark>max->totalmark) { maxpre=pre2; max=move2; } if(move1->next==max) //交换max和move1。 { pre1->next=max; move1->next=max->next; max->next=move1; move1=max; } else { s=move1->next; move1->next=max->next; max->next=s; maxpre->next=move1; pre1->next=max; move1=max; } } cout<<"已经按照从大到小排序"<next; int i; if(head->next==NULL){cout<<"没有学生记录,请添加"<<endl;system("pause"); return 0;} else { while(p) { cout<<"姓名:"<name; i=1; while(i!=SUBJECT+1) { cout<<"科目:"<mark[i-1].subject; cout<<" 成绩:"<mark[i-1].score; i++; } cout<next; } } system("pause"); return 0; } //6:从文件按读取记录 int student::display() { ifstream fin; char buf[100]; char str[25]; cout<<"请输入路径及文件名:"<<endl; cin.ignore(); gets(str); fin.open(str); if(!fin) { cout<<"没有此文件"<<endl; system("pause"); return 0; } while(fin) { fin.getline(buf,sizeof(buf)); cout<<buf<<endl; } system("pause"); return 0; } //8从文件中读取数据,并将数据保存在链表中 int student::readfiletolist() { ifstream fin; int i; char str[25]; cout<<"请输入路径及文件名:"<<endl; cin.ignore(); gets(str); fin.open(str); if(!fin) { cout<<"没有此文件"<totalmark=0; fin.getline(p->name,100,'*'); i=0; while(i!=SUBJECT) { fin.getline(p->mark[i].subject,100,'*'); fin>>p->mark[i].score; p->totalmark+=p->mark[i].score; i++; } if(head->next==NULL) { head->next=p; p->next=NULL; } else { p=head->next; head->next=p; } } cout<<"信息已经保存在链表中"<next==NULL) { cout<<"没有学生,请添加或者从文件中读取"<next; char findname[10]; int i; cout<name,findname)) { cout<<"经查找,找到该生信息如下:"<<endl<<endl; cout<<"姓名:"<name; i=1; while(i!=SUBJECT+1) { cout<<"科目:"<mark[i-1].subject; cout<<" 成绩:"<mark[i-1].score; i++; } cout<next; } cout<<"没有此学生,请添加或者从文件中读取"<<endl; system("pause"); return 0; } int showmenu() { int choice; char * menu[9]={ "1:输入学生成绩保存到链表\n", "2:计算每位学生总成绩\n", "3:按照总成绩大小对记录进行排序\n", "4:输出所有学生成绩到一个文件中\n", "5:显示新输入的学生信息\n", "6:从文件中读取信息\n", "7:将文件信息保存在链表中\n", "8:根据姓名查找学生记录\n", "9:结束程序\n" }; cout<<" "<<"*****************************************************"<<endl; cout<<" *"<<" "<<"学生成绩管理系统"<<" *"<<endl; cout<<" "<<"*****************************************************"<<endl; for(choice=0;choice<9;choice++) cout<<" "<<menu[choice]; cout<<" "<<"*****************************************************"<<endl; cout<<"please choose to continue"<>choice; } while(choice>9||choice<1); return choice; } int main() { int menuitem,flag=1; student stu; while(flag) { system("cls"); menuitem=showmenu(); switch(menuitem) { case 1:{stu.addstudent();break;} case 2:{stu.countmark();break;} case 3:{stu.sortbymark();break;} case 4:{stu.save();break;} case 5:{stu.show();break;} case 6:{stu.display();break;} case 7:{stu.readfiletolist();break;} case 8:{stu.searchbyname();break;} case 9:{flag=0;break;} } } return 0; }
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YXXYX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值