大一上学期C++课设-学生成绩管理系统

1.实现的功能

1.1.输出,查找

查找这是硬写的。。那个条件限制写的真的是一言难尽。。

1)按班级输出
2)按科目(数学,英语,c++的任意组合),按限制条件的输出
限制条件有:各科及平均分,总分的上下限。
3)输入学号查找学生,按设定的条件显示信息。
4)直接输出全部信息

1.2.输入

1)于指定位置插入任意个学生的数据
2)于结尾处添加数据

1.3.修改/删除

1)输入学号查找,找到之后输入要改的内容,不能手动改平均分和总分,其他的可以。
2)按学号查找后删除该学生的数据
3)清空所有数据

1.4. 排序数据

1)按照各科成绩,平均分或总分进行排序,从高到低或从低到高,这个排序的交换用了当时感觉非常诡异的方法,但是现在也懒得改了,确实能用=。=

1.5. 存储/读取数据

会把信息存到当前目录一个叫student_data的txt文件里,并且可以读取。
读写也是一样硬写出来的。。懒得改了。。

2.程序清单

#include<stdlib.h>
#include<stdio.h>
#include<direct.h>
#include<fstream>
#include<iostream>
#include<string.h>
#include<iomanip>
using namespace std;
//基本变量
int stumax = 0;
//读入的学生一共有多少
//输出选项
bool class_limited(false), score_limited(false), no_limited(false);
int selected_class(0);  
float min_math_score = 0, max_math_score = 99999, min_english_score = 0, max_english_score = 99999;
float min_program_score = 0, max_program_score = 99999;
float min_aver_score = 0, max_aver_score = 99999, min_total_score = 0, max_total_score = 9999999;
char selected_no[25], selected_subjects[4]; //字符串多存一个\0 //sub:[0]:数学  [1]:英语  [2]:高程
//修改用
char change_no[25];
struct student
{
    char no[25], name[25];//学生学号和名字,最多24字符
    int Class;//班级
    float math, english, program, ave, total;//分别是数学,英语,高程,平均分,总分,用float存,防止小数,平均分和总分不能手动修改
}a[100];//学生数组

void read_data()
{//读取数据
    stumax = 0;//设置学生数初始为0,因为要重新读取,舍弃现在已经有的数据。
    ifstream test("student_data.txt");
    //ifstream输入流,用这个可以读取文件,括号是构造函数,
    //把要读取的文件路径写在括号里,要加双引号,如果放在程序所在目录就不用加前面的路径,直接写文件名就行。
    //这样,就会读取这个文件了,接下来检测是不是真的找到并打开了这个文件,如果没找到,还要做其他处理
    if (!test.is_open())
    {//is_open()这个函数能检测是不是打开了这个文件,如果没有,返回假,写的时候很方便,!is_open就是没打开的意思。
        ofstream create("student_data.txt");
        //如果没打开,说明可能文件不存在,那就创建这个文件,ofstream是输出流,创建的时候如果文件不存在,就会自动创建空文件,
        //这样就可以新建文件了。
        //然后,就能像用cout一样向文件中输出数据了。
        //注:如ifstream刚创建时参数写的那个文件,输入就用的哪个文件,ofstream参数写的哪个文件, ofstream<<就向哪个文件输出。
        create << 0;//读取方式是先读取有多少人,再读取人数次数据,读到每个人的数据,输出0
        cout << "无数据,已新建存档";
        //提示没有找到数据,已经新建
        create.close();
        //不关闭很麻烦的,关闭输出流
    }
    else
    {
        test.close();//用于测试,在上面is_open测试下来的,如果打开了文件,证明已经存在,如果没有手动修改过,文件的内容
        //应该没问题,验证完毕,就把测试用的流关掉。
    }
    ifstream fin("student_data.txt");//重新开一个输入流,还打开student_data.txt,当然可以用test,只是为了和上面分开额。
    fin >> stumax;//和后面的写入顺序一样,先读入记录的学生总数,好知道要读入多少个学生数据
    //注1:fin和上面的create,test一样,只是自己起名为这个,可以随便起名。
    //注2:ifstream用法和cin一样,但是不需要键盘输入,而用文件输入,比如每空格/tab分隔输入,回车啥的。
    for (int i = 0; i < stumax; i++)
    {//循环stumax次,i=0,i<stumax正好是stumax次,比如i=0;i<3,取值是0,1,2三次。
        fin >> a[i].no >> a[i].name >> a[i].Class >> a[i].math >> a[i].english >> a[i].program;
        //和下面的输入顺序一样,是自己定义的存储方式,学号、名字、班级、成绩。
        a[i].total = a[i].math + a[i].english + a[i].program;//总成绩是三科之和
        a[i].ave = a[i].total / 3;//平均成绩是总成绩除以3
        //总成绩和平均成绩不写入/输入,直接计算,防止出错。
    }
    cout << "已读取" << stumax << "位学生的记录。" << endl;
    //提示读取了多少学生记录。
    fin.close();
    //关闭输入流
}
void write_data()                              //写入数据
{//写入数据
    ofstream fout("student_data.txt", ios::out);
    //打开输出流,前面参数是文件路径,后面参数是打开方式,因为这个out变量不在std命名空间里,所以要加ios::表示命名空间在ios
    //ios指的是In/Out Stream,std是STanDard
    if (!fout.is_open())
    {//如果打开失败,就退出,虽然一般不会出错吧。。
        cerr << "出现错误@=-=@!" << endl;
        exit(0);//调用这个系统函数直接退出
    }
    fout << stumax << endl;//先输出有多少人,这样读取的时候就知道读取多少次
    for (int i = 0; i < stumax; i++)//stumax次输出,先输出endl换行和后输出没啥区别,每个数据间加个空格,读取时好识别是不同的数据
        //就像cin输入时,一行输入多个数据要加空格。
        fout << endl << a[i].no << ' ' << a[i].name << ' ' << a[i].Class << ' ' << a[i].math << ' ' << a[i].english << ' ' << a[i].program;
    fout.close();//关闭
}
void enter_data()
{//基础输入
    fflush(stdin);
    //清空cin缓冲区,没啥用,防止多余数据读入,调用后cin里没读取的数据会被清空。
    for (int i = stumax; i < 100; i++)
    {//最多读取100个,但是可以中途打断
        //i = stumax的原因是,上次输入后有stumax个学生,所以追加时,下一个空位置的下标就是stumax,下标从0开始,所以很奇妙
        cin >> a[i].no;//输入学号,也可能是结束符,在输入学号时输入0即可结束输入,或者等到输入满100个后自动结束
        if (! (a[i].no[0] == '0' && a[i].no[1]=='\0') )
        {//如果输入的是"0",no里存的就是 0   \0  \0  \0  \0...如果输入别的
            //字符数组里默认存的全是\0,如果输入一个字符串,读入会依次到数组里,
            //但是输入最后会默认加个\0,所以假如输入“0”,读入的就是a[0] == 0
            //a[1] == \0,所以没有结束的条件就是不符合这个,就是!(a[0]==0&&a[1]=='\0')
            //如果要问这俩有什么区别,'0'是0这个字符的ascii码,\0的码值是0
            cin >> a[i].name >> a[i].Class >> a[i].math >> a[i].english >> a[i].program;
            //输入顺序
            a[i].total = a[i].math + a[i].english + a[i].program;
            a[i].ave = a[i].total / 3;
            //计算总分和平均分
            stumax++;//记录多了一个学生
        }
        else//假如打断或者装满了,就结束输入。
            break;
    }
    //每次输入完成后调用这个函数,把数据写入文件,防止忘记保存。。当然也不能撤销了。
    write_data();
}
void show()
{//基础输出
    if (stumax != 0)
    {//stumax 是学生数,如果不等于0,就说明有记录,如果有记录,则输出
        cout << " \t学号\t姓名\t班级\t数学\t英语\t高程\t平均分\t总分" << endl;//输出表头,这个是基本输出,测试用的
        for (int i = 0; i < stumax; i++)//setw是对齐用的宽度为12个字符算空格和输出的字符
            cout << i + 1 << "." << setw(12) << a[i].no << '\t' << a[i].name << '\t' << a[i].Class << '\t' << a[i].math << '\t' << a[i].english << '\t' << a[i].program << '\t' << fixed << setprecision(1) << a[i].ave << '\t' << a[i].total << endl;
    }
}
void insstu(int ins_start, int ins_num)
{//插入数据
    int ins_index = ins_start - 1;
    //如果要在第三个位置插入2个数据,输入参数就是ins_start = 3,ins_num = 2
    //因为第三个数据的下标其实是2,所以要-1,所以有ins_index = ins_start-1,是开始插入的位置
    //从这个开始,因为要插入ins_num个数据,所以要把之后的数据向后移ins_num位
    for (int i = (stumax - 1) + ins_num; i >= ins_index + ins_num; i--)                      //移位
    {//stumax - 1是原本的最后一个数据,+ins_num后就是它应该去的地方,直到移动到把ins_index 所在位置也挪到ins_num个之后。
        a[i] = a[i - ins_num];
    }//每次将ins_num个之前的数据移动到当前位置
        
    cout << "请输入学生的学号,名字,班级,数学,英语,高程成绩\n";//移动完成,输出提示
    for (int i = ins_index; i < ins_index + ins_num; i++)
    {//输入数据,计算,从ins_index开始,输入ins_num个
        cin >> a[i].no >> a[i].name >> a[i].Class >> a[i].math >> a[i].english >> a[i].program;
        a[i].total = a[i].math + a[i].english + a[i].program;
        a[i].ave = a[i].total / 3;
        stumax++;//加一个人
    }//没写中途退出
    write_data();//输入后,写入数据
}

void output_reset()
{//重置查找选项
    class_limited = 0, score_limited = 0, selected_class = 0, memset(selected_subjects, 1, sizeof(selected_subjects));   //osub:1:数学  2:英语  3.高程
    min_math_score = 0, max_math_score = 99999, min_english_score = 0, max_english_score = 99999, min_program_score = 0, max_program_score = 99999, min_aver_score = 0, max_aver_score = 99999, min_total_score = 0, max_total_score = 999999;
}
void output_lim()
{//查找
    cout << endl;
    int j = 1;    //记录输出数量
    cout << "  \t学号\t姓名\t班级";
    if (selected_subjects[0])cout << '\t' << "数学";
    if (selected_subjects[1])cout << '\t' << "英语";
    if (selected_subjects[2])cout << '\t' << "高程";
    if (selected_subjects[0] && selected_subjects[1] && selected_subjects[2])
        cout << '\t' << "平均分" << '\t' << "总分";  //列表表头
    cout << endl;
    for (int i = 0; i < stumax; i++)
    {
        if ((!no_limited || memcmp(a[i].no, selected_no, 25) == 0) && (!class_limited || a[i].Class == selected_class) && (a[i].math >= min_math_score && a[i].math <= max_math_score) && (a[i].english >= min_english_score && a[i].english <= max_english_score) && (a[i].program >= min_program_score && a[i].program <= max_program_score) && (a[i].ave >= min_aver_score && a[i].ave <= max_aver_score) && (a[i].total >= min_total_score && a[i].total <= max_total_score))
        {// 全部条件满足时进行输出
            cout << j << '.' << setw(12) << a[i].no;
            cout << '\t' << a[i].name << '\t' << a[i].Class << '\t';
            if (selected_subjects[0]) cout << a[i].math << '\t';
            if (selected_subjects[1]) cout << a[i].english << '\t';
            if (selected_subjects[2]) cout << a[i].program << '\t';
            if (selected_subjects[0] && selected_subjects[1] && selected_subjects[2])   //全部显示时显示平均分和总成绩
                cout << fixed << setprecision(1) << a[i].ave << '\t' << a[i].total;
            cout << endl;
            j++;
        }
    }
    if (j == 1)  //显示数量判定
        cout << "未查找到符合条件的学生QAQ 您可以修改条件。。" << endl;
    else
        cout << "查找到了" << j - 1 << "位符合条件的学生!" << endl;
    system("pause");//暂停
}
void outPut_menu()
{//查找菜单
    int outputSelect(0);
    while (1)
    {
        cout << "-------请选择查找方式--------" << endl;
        cout << "1.按班级输出     2.指定学号查找" << endl;
        cout << "3.显示指定科目   4.按成绩输出" << endl;
        cout << "5.清除条件       6.显示目前条件" << endl;
        cout << "9.直接输出(测试) 0.退出查询" << endl;
        cout << "-----------------------------" << endl;
        cout << "多条件查找请逐个添加 " << endl;
        cin >> outputSelect;
        switch (outputSelect)
        {
        case 1:
            class_limited = true;//设置标志
            cout << "请输入您想查看的班级,输入0来显示全部班级:\n";
            cin >> selected_class;
            if (selected_class == 0) class_limited = 0;
            output_lim();
            break;
        case 2:
            no_limited = 1;    //激活条件变量
            output_reset(); // 重置变量以从全部学生中查找
            cout << "请输入您想查找的学生学号:";
            cin >> selected_no;
            output_lim();
            no_limited = 0;    //复位条件变量
            break;
        case 3:
            memset(selected_subjects, 0, sizeof(selected_subjects));  //清空这里在清空的时候写了3*sizeof,居然把struct a 里的数据都清掉了!!!导致a.math的数据都没了。   找了半天才发现!
            cout << "请输入您想显示的科目序号" << endl;
            cout << "1.数学   2.英语   3.高程" << endl;
            cout << "输入“12”以显示数学和英语" << endl;
            cin >> selected_subjects;
            for (int i = 0; i < 3; i++)
            {
                if (selected_subjects[i] != '\0') selected_subjects[(selected_subjects[i] - 49)] = 1;
            }
            output_lim();
            break;
        case 4:

            cout << "请输入您需要限制的科目:" << endl;
            cout << "1.英语 2.数学 3.高程 4.平均分 5.总分" << endl;
            cin >> outputSelect;
            cout << "请输入您需要查找的最低分与最高分:" << endl;
            switch (outputSelect)
            {
            case 1:
                cin >> min_english_score >> max_english_score;
                break;
            case 2:
                cin >> min_math_score >> max_math_score;
                break;
            case 3:
                cin >> min_program_score >> max_program_score;
                break;
            case 4:
                cin >> min_aver_score >> max_aver_score;
                break;
            case 5:
                cin >> min_total_score >> max_total_score;
                break;
            }
            output_lim();
            break;
        case 5:
            output_reset();
            cout << "成功!" << endl;
            break;
        case 6:
            cout << "目前显示" << selected_class << "班,显示科目";
            if (selected_subjects[0]) cout << "数学 ";
            if (selected_subjects[1]) cout << "英语 ";
            if (selected_subjects[2]) cout << "高程 ";
            cout << endl;
            break;
        case 9:
            show();
        }
        if (outputSelect == 0)
        {
            output_reset();  //退出时复位变量
            break;
        }
    }
}

int change(int insa, char posa[])
{//更改数据
    int asw = 0;
    if (memcmp(posa, "学号", 4) == 0) { cin >> a[insa].no; asw = 1; }
    if (memcmp(posa, "姓名", 4) == 0) { cin >> a[insa].name; asw = 1; }
    if (memcmp(posa, "班级", 4) == 0) { cin >> a[insa].no; asw = 1; }
    if (memcmp(posa, "数学", 4) == 0) { cin >> a[insa].math, asw = 1; }
    if (memcmp(posa, "英语", 4) == 0) { cin >> a[insa].english; asw = 1; }
    if (memcmp(posa, "高程", 4) == 0) { cin >> a[insa].program; asw = 1; }
    a[insa - 1].total = a[insa - 1].math + a[insa - 1].english + a[insa - 1].program, a[insa - 1].ave = a[insa - 1].total / 3;
    write_data();
    return asw;
}
void dlt(int pos)
{//删除数据
    for (int i = pos; i < stumax; i++)
    {//覆盖
        a[i] = a[i + 1];
    }
    stumax--;
    write_data();
}
void searchstuNo()
{//更改删除菜单
    int recno(-1);
    char yon;
    int changeSelect;
    char changea[15];
    for (int i = 0; i < stumax; i++)
        if (memcmp(a[i].no, change_no, 25) == 0)
        {
            recno = i;
            break;
        }
    if (recno == -1) cout << "未找到学生!" << endl;
    else
    {
        cout << "\t学号\t姓名\t班级\t数学\t英语\t高程\t平均分\t总分" << endl;
        cout << recno << '.' << setw(12) << a[recno].no;
        cout << '\t' << a[recno].name << '\t' << a[recno].Class << '\t' << a[recno].math << '\t' << a[recno].english << '\t' << a[recno].program << '\t' << fixed << setprecision(1) << a[recno].ave << '\t' << a[recno].total;
        cout << endl;
        cout << "请选择-----------------" << endl;
        cout << "1.更改数据   2.删除数据" << endl;
        cout << "-----------------------" << endl;
        cin >> changeSelect;
        switch (changeSelect)
        {//更改或删除
        case 1:
            cout << "请输入您想修改的信息:学号、姓名、班级、数学、英语、高程" << endl;
            cin >> changea;
            if (change(recno, changea))
                cout << "修改成功!" << endl;
            else
                cout << "修改失败!" << endl;
            break;
        case 2:
            cout << "您确定吗?Y是N否" << endl;
            cin >> yon;
            if (yon == 'y' || yon == 'Y')
                dlt(recno);
            if (yon == 'n' || yon == 'N')
                break;
        default:
            cout << "输入错误!" << endl;
        }
    }
}
void sort_data()
{//排序
    int sorta(0), sortc;
    student temp;
    cout << "请输入需要排序的选项:\n1.数学 2.英语 3.高程 4.平均分 5.总分" << endl;
    cin >> sortc;
    sortc -= 1;
    cout << "请输入排序方式:1.由高到低  2.由低到高" << endl;
    cin >> sorta;
    student t;
    for (int i = 0; i < stumax - 1; i++)
        for (int j = i + 1; j < stumax; j++)
        {
            float sorts[5] = { a[i].math,a[i].english,a[i].program,a[i].ave,a[i].total };
            float sortss[5] = { a[j].math,a[j].english,a[j].program,a[j].ave,a[i].total };
            if ((sorts[sortc] < sortss[sortc] && sorta == 1) || (sorts[sortc] > sortss[sortc] && sorta == 2))
            {
                t = a[i];
                a[i] = a[j];
                a[j] = t;
            }
        }
}
int start()
{//主菜单
    int mainSelect;
    int insloc, insnum;  //插入位置
    read_data();
    while (1)
    {
        system("pause");//如果不想清屏把这两句删了就行
        system("cls");
        cout << "---欢迎使用学生信息管理系统---" << endl << endl;;
        cout << "1.输入数据        2.查找数据" << endl;
        cout << "3.修改数据        4.重置数据" << endl;
        cout << "5.显示数据        6.存储数据" << endl;
        cout << "7.排序数据        0.退出系统" << endl;
        cout << "------------------------------" << endl;
        cout << stumax << "个学生的信息已读取。" << endl;
        cout << "请选择:\n";
        cin >> mainSelect;
        switch (mainSelect)
        {
        case 1:
            cout << "请选择输入方法:\n1.指定位置添加\t2.于结尾处添加" << endl;
            cin >> mainSelect;
            switch (mainSelect)
            {
            case 1:
                if (stumax == 0)
                {
                    cout << "没有数据!" << endl;
                    break;
                }
                show();
                cout << "请您输入您想添加的位置与添加的人数:" << endl;
                cin >> insloc >> insnum;
                if (insloc <= 0 || insloc >= stumax)
                    cout << "你想干嘛?没有这个位置。" << endl;
                else
                    insstu(insloc, insnum);
                break;
            case 2:
                cout << "请输入学生的学号,名字,班级,数学,英语,高程成绩,于学号处输入0来结束:\n";
                enter_data();
                break;
            default:
                cout << "您的输入有误!已返回。" << endl;
                break;
            }
            break;
        case 2: if (!stumax)
        {
            cout << "无数据!\n"; break;
        }
              else
        {
            outPut_menu(); break;
        }
        case 3:
            output_lim();
            cout << "请输入您想要修改的学生的学号:(不支持修改平均分和总分)" << endl;
            cin >> change_no;
            searchstuNo();
            break;
        case 4:
            int reset;
            cout << "您真的想重置数据吗?(0.否   1.是)" << endl;
            cin >> reset;
            if (reset)
            {
                for (int i = 0; i < 100; i++)
                    memset(&a[i], 0, sizeof(struct student));
                stumax = 0;
                cout << "已完成!\n";
                write_data();  //写入
            }
            else
                cout << "已取消!" << endl;
            break;
        case 5:
            show();
            break;
        case 6:
            write_data();
            system("cls");
            cout << "成功!" << endl;
            break;
        case 7:
            sort_data();
            write_data();
            break;
        case 0:
            return 0;
        default:
            cout << "您的输入有误!" << endl;
            break;
        }
    }
}
int main()
{
    start();
    return 0;
}




3.运行结果

运行结果:
菜单
添加学生。
在这里插入图片描述
显示指定科目。
在这里插入图片描述
按分数查找。

4.吐槽

这个程序写的真的很强行= =但是当时真的觉得自己好强啊!
纪念一下吧= =

  • 66
    点赞
  • 326
    收藏
    觉得还不错? 一键收藏
  • 48
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值