C++实现学生管理系统


实验要求

实验要求:将班上同学的信息(编号(001对应第一个,008对应第八个),姓名,性别,年龄,学校,年级,班级,爱好……),使用自己设计的结构体来存储。并在此基础上结合之前学的vector设计一个管理系统,并按以下要求实现
1.main函数大致按以下框架实现。(需要增加自己的系统功能就自己再加)
在这里插入图片描述

2.增加学生信息---构造一个学生,将其保存到vector里面
3.修改学生信息---输入学生编号,以及对应自己想修改的信息,比如修改001号学生的姓名,也可以修改001号学生的年龄
4.删除学生信息---输入学生编号,删除该学生信息
5.查询学生信息---输入学生编号,输出其具体信息,并且查询全部学生的具体信息

6.将程序中所得到的学生信息存储到文件中。(一行一个学生)(可以在退出整个程序时,将程序所有的学生信息写入文件,也可以自己想一种更高效的方式)
7.将文件中的学生信息读取到程序中。(每次程序运行时,需要先从文件中读入已有学生信息以免反复输入重复的学生信息)


一、实验平台

操作系统:win10
语言:C++17
IDE:Clion/Dev-cpp/Red-Panda

二、代码

1.结构体以及相关变量

学生Struct结构体

struct  Student{
    int no,age;
    string name,sex,school,class_1,hobby;
    //class是一个C++的关键字,所以用class_1表示班级
    Student(){

    }
    Student(int no1){
        no = no1;
    }
};
vector<Student> banji;//banji代表存储快班所有学生的动态数组

banji是作为全局变量来使用的。struct里面的两个函数是构造函数(我在使用结构体的时候喜欢加上一两个构造函数来简化代码)

//假设上面的结构体中再加一个构造函数。
Student(int no1,int age1,string name1,string sex1,string shcool1){
	no=no1;
	age=age1;
	name=name1;
	sex=sex1;
	school=school1;
}
//那么我在构造一个学生对象的时候就可以这样做
Studnet s(1,48,"张三","男","社会大学");
//而不是像下面这样啰啰嗦嗦的
Student s;
s.no= 1;
s.age= 48;
s.name= "张三";
s.sex= "男";
s.school= "社会大学";

2.相关函数实现过程

(1)判断一个学生是否已经存在

int isInBanji(Student& s){
    for(int i=0;i<banji.size();i++){
        if(s.no==banji[i].no){
            return i;
        }
    }
    return -1;
}

根据学号判断学生是否存在,该处使用-1代表不存在,0~n-1代表其下标。不简化为bool类型的函数,是为了在后面需要用到查找学生下标好直接调用


(2)从文件中读写学生信息

void writeToFile(){
    ofstream fout("student.txt");
    for(auto& s:banji) {
        fout << s.no << " " << s.name << " " << s.sex << " " << s.age << " " << s.school << " " << s.class_1 << " "
             << s.hobby << endl;
    }
    fout.close();
}
void readFromFile(){
    ifstream fin("student.txt");
    Student s;
    while(!fin.eof()){
        fin>>s.no>>s.name>>s.sex>>s.age>>s.school>>s.class_1>>s.hobby;
        if(fin.fail())
            break;
        banji.push_back(s);
    }
    fin.close();
}

创建一个student.txt的文件来存储学生信息。ifstream,ofstream来进行对应的文件操作。特别注意的是在读文件时,需要加上fin.fail()的判断,不然文件最后一行会被读两次。最后在操作完文件后,不要忘记文件的关闭-close();

(3)增加学生

void addStu(){
    Student s;
//    string op[6]={"编号","姓名",};
    cout<<"输入添加学生的 编号 姓名 性别 年龄 学校 班级 爱好:\n";
    cin>>s.no>>s.name>>s.sex>>s.age>>s.school>>s.class_1>>s.hobby;
    if(isInBanji(s)==-1) {
        banji.push_back(s);
        cout<<"成功添加一个学生!"<<endl;
        return ;
    }
    cout << "该编号学生已经存在,无法反复添加!" << endl;
}

首先声明一个学生对象s,然后输出一串提示信息,依次输入对应的信息。根据编号来查找注意的是不能添加重复编号的学生。输入信息无误,就调用vector自带的函数push_back(),把学生压入向量

(4)删除学生

void delStu(){
    cout<<"输入需要删除的学生编号:"<<endl;
    int no;
    cin>>no;
    Student s(no);//调用Student(int no1)构造函数
    int ind = isInBanji(s);
    if(ind!=-1){
        banji.erase(banji.begin()+ind);//删除下标为ind的学生
        cout<<"成功删除一个学生!"<<endl;
        return ;
    }
    cout<<"该编号学生不存在,无法删除!"<<endl;
}

(5)修改学生

void changeStu(){
    cout<<"输入需要修改的学生的编号:";
    int no;
    cin>>no;
    Student s(no);
    int ind = isInBanji(s);
    if(ind==-1){
        cout<<"该编号学生不存在,无法修改!"<<endl;
        return ;
    }
    int op;
    while(1){
        cout<<"0-退出修改\n"
              "1-修改姓名\n"
              "2-修改性别\n"
              "3-修改年龄\n"
              "4-修改学校\n"
              "5-修改班级\n"
              "6-修改爱好\n";
        cin>>op;
        if(op==0)break;
        cout<<"原信息:";
        switch (op) {
            case 1:cout<<banji[ind].name<<"   修改后:";
                cin>>banji[ind].name;break;
            case 2:cout<<banji[ind].sex<<"   修改后:";
                cin>>banji[ind].sex;break;
            case 3:cout<<banji[ind].age<<"   修改后:";
                cin>>banji[ind].age;break;
            case 4:cout<<banji[ind].school<<"   修改后:";
                cin>>banji[ind].school;break;
            case 5:cout<<banji[ind].class_1<<"   修改后:";
                cin>>banji[ind].class_1;break;
            case 6:cout<<banji[ind].hobby<<"   修改后:";
                cin>>banji[ind].hobby;break;
        }
    }
}

同样的套路,定义一个学生对象,通过输入对应的编号,先用isInBanji函数查出该学生的下标,然后通过提示信息,进行下一步的修改。

(6)查询学生

void findStu(){
    cout<<"输入需要查询的学生编号(查询全部输入-1):\n";
    int no;
    cin>>no;
    if(no==-1){
        printf("%3s %3s %2s %3s %10s %8s %20s\n",
               "编号","姓名","性别","年龄","学校","班级","爱好");
        for(auto& s: banji){
            printf("%3d %3s %2s %3d %10s %8s %20s\n",
                   s.no,s.name.c_str(),s.sex.c_str(),s.age,
                   s.school.c_str(),s.class_1.c_str(),s.hobby.c_str());
//            cout<<s.no<<" "<<s.name<<" "<<s.sex<<" "<<s.age<<" "<<s.school<<" "<<s.class_1<<" "<<s.hobby<<endl;
        }
    }
    else{
        Student s(no);
        int ind = isInBanji(s);
        if(ind == -1){
            cout<<"该编号学生不存在,请输入正确的编号!"<<endl;
        }
        else{
            s = banji[ind];
            printf("%3s %3s %2s %3s %10s %8s %20s\n",
                   "编号","姓名","性别","年龄","学校","班级","爱好");
            printf("%3d %3s %2s %3d %10s %8s %20s\n",
                   s.no,s.name.c_str(),s.sex.c_str(),s.age,
                   s.school.c_str(),s.class_1.c_str(),s.hobby.c_str());
        }
    }
}

提供两种查询方法,查询全部学生,查询单个学生。查全部的就for循环遍历。查单个的就用isInBanji函数查出对应下标,再printf()输出就OK啦

(7)main函数的实现

int main() {
    int option;
    readFromFile();
    while(1){
        cout<<"0-退出\n";
        cout<<"1-增加学生\n";
        cout<<"2-删除学生\n";
        cout<<"3-修改学生\n";
        cout<<"4-查询学生\n";
        cout<<"选择系统功能:";
        cin>>option;
        if(option==0){
            break;
        }
        switch (option) {
            //调用自己实现的函数功能
            case 1:addStu();break;
            case 2:delStu();break;
            case 3:changeStu();break;
            case 4:findStu();break;
            default:cout<<"请输入正确的编号\n";
        }
    }
    writeToFile();
}

在main函数开始处,把文件的数据读入到banji中。然后一个while()循环,开始人机交互,根据提示输出对应的选项,调用写好的增删改查功能。最后退出循环后,将banji的所有数据写回到文件中(这里直接用的全覆盖方式)

3.整体代码

#include <bits/stdc++.h>
using namespace std;
//#define rep(i, a, b) for(int i=a;i<b;i++)
//#define rrep(i, a, b) for(int i=a;i>b;i--)

struct  Student{
    int no,age;
    string name,sex,school,class_1,hobby;
    //class是一个C++的关键字,所以用class_1表示班级
    Student(){

    }
    Student(int no1){
        no = no1;
    }
};

vector<Student> banji;//banji代表存储快班所有学生的动态数组

/*
 * 返回-1代表在班级中没有查到该学生,否则返回学生在其中的下标
 */
int isInBanji(Student& s){
    for(int i=0;i<banji.size();i++){
        if(s.no==banji[i].no){
            return i;
        }
    }
    return -1;
}

void writeToFile(){
    ofstream fout("student.txt");
    for(auto& s:banji) {
        fout << s.no << " " << s.name << " " << s.sex << " " << s.age << " " << s.school << " " << s.class_1 << " "
             << s.hobby << endl;
    }
    fout.close();
}
void readFromFile(){
    ifstream fin("student.txt");
    Student s;
    while(!fin.eof()){
        fin>>s.no>>s.name>>s.sex>>s.age>>s.school>>s.class_1>>s.hobby;
        if(fin.fail())
            break;
        banji.push_back(s);
    }
    fin.close();
}

void addStu(){
    Student s;
//    string op[6]={"编号","姓名",};
    cout<<"输入添加学生的 编号 姓名 性别 年龄 学校 班级 爱好:\n";
    cin>>s.no>>s.name>>s.sex>>s.age>>s.school>>s.class_1>>s.hobby;
    if(isInBanji(s)==-1) {
        banji.push_back(s);
        cout<<"成功添加一个学生!"<<endl;
        return ;
    }
    cout << "该编号学生已经存在,无法反复添加!" << endl;
}

void delStu(){
    cout<<"输入需要删除的学生编号:"<<endl;
    int no;
    cin>>no;
    Student s(no);//调用Student(int no1)构造函数
    int ind = isInBanji(s);
    if(ind!=-1){
        banji.erase(banji.begin()+ind);//删除下标为ind的学生
        cout<<"成功删除一个学生!"<<endl;
        return ;
    }
    cout<<"该编号学生不存在,无法删除!"<<endl;
}

void changeStu(){
    cout<<"输入需要修改的学生的编号:";
    int no;
    cin>>no;
    Student s(no);
    int ind = isInBanji(s);
    if(ind==-1){
        cout<<"该编号学生不存在,无法修改!"<<endl;
        return ;
    }
    int op;
    while(1){
        cout<<"0-退出修改\n"
              "1-修改姓名\n"
              "2-修改性别\n"
              "3-修改年龄\n"
              "4-修改学校\n"
              "5-修改班级\n"
              "6-修改爱好\n";
        cin>>op;
        if(op==0)break;
        cout<<"原信息:";
        switch (op) {
            case 1:cout<<banji[ind].name<<"   修改后:";
                cin>>banji[ind].name;break;
            case 2:cout<<banji[ind].sex<<"   修改后:";
                cin>>banji[ind].sex;break;
            case 3:cout<<banji[ind].age<<"   修改后:";
                cin>>banji[ind].age;break;
            case 4:cout<<banji[ind].school<<"   修改后:";
                cin>>banji[ind].school;break;
            case 5:cout<<banji[ind].class_1<<"   修改后:";
                cin>>banji[ind].class_1;break;
            case 6:cout<<banji[ind].hobby<<"   修改后:";
                cin>>banji[ind].hobby;break;
        }
    }
}

void findStu(){
    cout<<"输入需要查询的学生编号(查询全部输入-1):\n";
    int no;
    cin>>no;
    if(no==-1){
        printf("%3s %3s %2s %3s %10s %8s %20s\n",
               "编号","姓名","性别","年龄","学校","班级","爱好");
        for(auto& s: banji){
            printf("%3d %3s %2s %3d %10s %8s %20s\n",
                   s.no,s.name.c_str(),s.sex.c_str(),s.age,
                   s.school.c_str(),s.class_1.c_str(),s.hobby.c_str());
//            cout<<s.no<<" "<<s.name<<" "<<s.sex<<" "<<s.age<<" "<<s.school<<" "<<s.class_1<<" "<<s.hobby<<endl;
        }
    }
    else{
        Student s(no);
        int ind = isInBanji(s);
        if(ind == -1){
            cout<<"该编号学生不存在,请输入正确的编号!"<<endl;
        }
        else{
            s = banji[ind];
            printf("%3s %3s %2s %3s %10s %8s %20s\n",
                   "编号","姓名","性别","年龄","学校","班级","爱好");
            printf("%3d %3s %2s %3d %10s %8s %20s\n",
                   s.no,s.name.c_str(),s.sex.c_str(),s.age,
                   s.school.c_str(),s.class_1.c_str(),s.hobby.c_str());
        }
    }
}

int main() {
    int option;
    readFromFile();
    while(1){
        cout<<"0-退出\n";
        cout<<"1-增加学生\n";
        cout<<"2-删除学生\n";
        cout<<"3-修改学生\n";
        cout<<"4-查询学生\n";
        cout<<"选择系统功能:";
        cin>>option;
        if(option==0){
            break;
        }
        switch (option) {
            //调用自己实现的函数功能
            case 1:addStu();break;
            case 2:delStu();break;
            case 3:changeStu();break;
            case 4:findStu();break;
            default:cout<<"请输入正确的编号\n";
        }
    }
    writeToFile();
}

总结

通过本实验,我学到了如何解决ifstream读取文件末尾会读两次的问题。

  • 13
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值