学生成绩管理(链表)c++

二、设计与实现

1、设计思想

设计一个Student类,Student类中包括对学生信息的各种操作函数,并设计一个StuMessage结构,用以存储学生信息,Student类公有继承用StuMessage结构实例化的List模板类。

Student类中有实现录入、修改、添加、删除、显示、查询、分析、清空学生成绩,学生成绩排序,学生信息存档的成员函数。

StuMessage结构中有表示学生五门成绩、排名、学号、姓名的变量。

List类即单链表类,其中包括对单链表的各种操作函数以及有关的变量。

最终,在主函数中生成Student类的对象,实现相应的功能。

2、类结构

2-1 类结构

  1. 主要数据结构

学生成绩用单链表存储,方便插入和删除等对学生成绩的处理操作,实现动态管理。一个学生对应一个结点,使用链表的基本算法实现对学生成绩表管理功能。

  1. 算法设计

图4.1 主函数流程图

图4-2 删除成绩和修改成绩的流程图

图4-3 录入学生成绩和添加成绩成员函数的流程图

图4-4 成绩排序及成绩分析成员函数的流程图

图4-5 重载运算符<<和查找学生成绩成员函数的流程图

图4-6 保存学生信息和清空信息的流程图

5、核心代码展示

struct StuMessage//存储学生信息的结构类型

{

    int order=-1;

    string number="";

    string name="";

    int Math=-1;

    int OPP=-1;

    int English=-1;

    int History=-1;

    int Physics=-1;

};

void Student::Sort_Sum(int subject, int order)  //成绩排名(subject为按何种成绩排序的代号,order为升序和降序的代号)

{

    int i, j, sum1, sum2, lastorder;

    class ListNode<struct StuMessage>* head = GetHead();

    class ListNode<struct StuMessage>* p;

    struct StuMessage stu1, stu2;

    int length = GetLength();

    if (length > 1)

    {

           for (i = 2;i <= length;i++)

           {

                  for (j = 1;j < i;j++)

                  {

                         stu1 = Get_Order(j);

                         stu2 = Get_Order(i);

                         switch (subject)   //   选择排序依据的数据

                         {

                         case 1:sum1 = stu1.English + stu1.History + stu1.Math + stu1.OPP + stu1.Physics;

                                   sum2 = stu2.English + stu2.History + stu2.Math + stu2.OPP + stu2.Physics;break;

                         case 2:sum1 = stu1.English;sum2 = stu2.English;break;

                      ……//sum1,sum2中存入相应成绩

                         default:cout << "Error\n";exit(1); //遇到非法输入则退出

                         }

                         if (order == 1)  //排名升序下的直插排序

                         {

                                if (sum1 < sum2)

                                {

                                       Remove_Order(i);

                                       Insert(stu2, j);

                                }

                         }

                         else if (order == 2) //排名降序下的直插排序

                         {

                                ……//类似于升序下的代码

                         }

                         else  //遇到非法输入退出程序

                         {   cout << "Error!";exit(1);   }

                  }

           }

    }

    p = head->next;

    sum1 = sum2 = -1;

    if (order == 1) //排名升序下为每个学生写入排名 

    {

           for (i = 1;i <= length;i++)

           {

                  sum2 = sum1;

                  stu1 = p->data;    //第i个学生的学生信息存入stu1

                  switch (subject)   //   选择排序依据的数据

                  {

                  case 1:sum1 = stu1.English + stu1.History + stu1.Math + stu1.OPP + stu1.Physics;break;

                  case 2:sum1 = stu1.English;break;

                ……

                  default:{ cout << "Error\n";

                                         exit(1); //遇到非法输入则退出

                       }

                  }

                  if (sum1 == sum2)  //同上一个人的成绩相同

                  {

                         p->data.order = lastorder; //上个人的排名即为此人的排名

                         p = p->next;

                  }

                  else

                  {

                         p->data.order = i;  //成绩与前一个人不同时,排名为序号

                         p = p->next;

                         lastorder = i;

                  }

           }

    }

    else if (order == 2)//降序下,为每个学生写入排名     

    {      ……//同升序下的代码相似

    }

    else  //遇到非法输入,程序退出

    {   cout << "Error!";exit(1);   }

}

void Student::Analyse()  //成绩分析

{

    int a;

    while (1)

    {

           cout << "\n想要分析哪一门成绩?请输入相应序号(1:物理  2:数学  3:英语  4:历史  5:OPP  6:总分):  ";

           cin >> a;

           if (a != 1 && a != 2 && a != 3 && a != 4 && a != 5 && a != 6)  {      cout << "\n输入序号有误,请重新输入!" << endl;   }

           else {break;}

    }

    cout << "\n\t成绩分析如下: \n" << endl;

    class ListNode<struct StuMessage>* head = GetHead();

 class ListNode<struct StuMessage>* p = head->next;

    struct StuMessage stu;

    int you = 0, liang = 0, zhong = 0, jige = 0, bujige = 0, num = 0,b,max = -1, min = 1000;

    double average = 0;

    {

           while (p)

           {

                  stu = p->data;

                  switch (a)

                  {

                  case 1:b = stu.Physics;break;

               ……//将要分析的科目的成绩保存到b中

                  }

                  if (a <= 5)  //当只有一门科目时

                         switch (b / 10)

                         {

                         case 10:

                         case 9:you++;break;

                         case 8:liang++;break;

                         case 7:zhong++;break;

                         case 6:jige++;break;

                         default:bujige++;

                         }

                  else  //当分析总分时

                         switch (b / 50)

                         {

                         ……//代码和a<<5时相似

                         }

                  average += b;

                  max = (b > max) ? b : max;       min = (b < min) ? b : min;

                  p = p->next;

                  num++;

           }

           average = average / num;

           ……//显示成绩分析结果

    }

}

void Student::AlterGrade()  //修改学生成绩

{

    int i,a;

    string num;

    float newgrade;

    ListNode<struct StuMessage>* head = GetHead();   ListNode<struct StuMessage>* p = NULL;

    cout << "请输入修改成绩对应的学号";

    cin >> num;

    cout << "请输入修改科目(1:物理  2:数学  3:英语  4:历史  5:OPP)";

    cin >> a;

    cout << "请输入修改后的成绩";

    cin >> newgrade;

    for (i = 1; i <= length; i++)//找该学号学生

    {

           p = Find_Order(i);      if (num == p->data.number)  {break;}

    }

    if (i > length) {cout << "未找到该学号的学生\n" << endl;}

    else

    {

           struct StuMessage& stu = p->data;

           if (p == NULL || p == head)

           {

                  cout << "Error!" << endl;

                  exit(1);

           }

           else

           {

                  switch (a)

                  {case 1: stu.Physics = newgrade;break;

                  ……//改变对应科目的成绩

                  case 5: stu.OOP = newgrade;break;

                  default:cout << "序号错误\n" << endl;

                  }

                  cout << "修改成功\n" << endl;

           }

    }

}

void Student::AddGrade()  //添加成绩

{

    struct StuMessage stu;

    cout << "请输入学号:";

    cin >> stu.number;

    cout << "请输入姓名:";

    cin >> stu.name;

    cout << "请依次输入成绩(1:物理  2:数学  3:英语  4:历史  5:OPP)\n";

    cin >> stu.Physics >> stu.Math >> stu.English >> stu.History >> stu.OOP;

    Insert(stu, length + 1);

    cout << "添加成功\n" << endl;

}

void Student::DeleteGrade() //删除成绩

{

    ListNode<StuMessage>* p;

    int i;

    string num;   //待删除成绩对应学号

    cout << "请输入学号";

    cin >> num;

    for (i = 1; i <= length; i++)

    {

           p = Find_Order(i);

           if (num == p->data.number)

           {      Remove_Order(i);      break;    }

    }

    if (i > length)

    {      cout << "未找到该学号的学生\n" << endl; }

    else

    {      cout << "删除成功\n" << endl; }

}

void Student::Save()  //将学生信息保存到指定的txt文件

{

    int i;

    struct StuMessage stu;

    ofstream fw;

    char a[100];

    cout << "输入文件路径(.txt文件)(不含空格):";

    cin >> a;

    fw.open(a);  //打开该文件

    if (fw.is_open())   //判断是否打开成功

    {

           if (a[strlen(a) - 1] == 't' && a[strlen(a) - 2] == 'x' && a[strlen(a) - 3] == 't' && a[strlen(a) - 4] == '.') //判断是不是txt文件

           {

                  for (i = 1; i <= length; i++)

                  {

                         stu = Get_Order(i);

                         fw << stu.number << " " << stu.name << " " << stu.Physics << " " << stu.Math << " " << stu.History << " " << stu.OOP << " " << stu.English << endl; //将学生信息写入文件

                  }

                  cout << "已保存成功!\n";

           }

           else  //不是txt文件,输出警告

           {      cout << "您输入的不是txt文件!\n" << endl; }

           fw.close(); //关闭文件

    }

    else //未成功打开文件

    {      cout << "打开文件失败!\n" << endl;}

}

void Student::Find()  //查询学生信息

{

    int i;

    string num;

    struct StuMessage stu; 

    cout << "请输入学号:";

    cin >> num;

    for (i = 1; i <= length; i++)

    {

           stu = Get_Order(i);

           if (stu.number == num)   //从链表开头找,直到找到该学号的学生

           {

             ……//省略显示学生信息有关的代码

                  break;

           }

    }

    if (i > length)     //未找到该学号的学生

    {      cout << "未找到该学生!\n" << endl; }

    else if (stu.order == -1)  //如果还没有排名,输出警告

    {      cout << "尚未排名,请返回主菜单排名" << endl;  }

}

void Student::EnterStuInformation()

{

    struct StuMessage stu;

    int point = 0,i, j = 0;

    ifstream fr;

    char a[100],line[100];

    float score;

    cout << "输入文件路径(txt文件)(不含空格):";

    cin >> a;

    fr.open(a);     //打开该文件

    if (fr.is_open())  //判断是否打开

    {

           if (a[strlen(a) - 1] == 't' && a[strlen(a) - 2] == 'x' && a[strlen(a) - 3] == 't'&& a[strlen(a) - 4] == '.') //判断是不是txt文件

           {

                  while (!fr.eof())  //判断是否读到末尾

                  {

                         fr >> stu.number;

                         if (fr.eof())  //判断是否读到末尾

                         {break;}

                         fr >> stu.name;

                         for (i = 1; i <= 5; i++)

                         {

                                fr >> line;

                                for (j = 0, score = 0,point=0; line[j]; j++)

                                {

                                       if (point == 0 && line[j] >= '0' && line[j] <= '9')

                                       {      score = score * 10 + line[j] - '0';  //没碰到小数点,将字符串表示的数转化为数字

                                       }

                                       else if (point !=0 && line[j] >= '0' && line[j] <= '9')

                                       {             score = score + pow(10, -(j - point))*(line[j]-'0');       }

                                       else if(line[j]=='.')

                                       {      point = j;       }

                                }

                                switch (i)

                                {

                                case 1:stu.Physics = score; break;

                                ……}

                         }

                         Insert(stu, length + 1);

                  }

                  cout << "录入成功\n" << endl;

           }

           else

           {      cout << "您输入的不是txt文件!\n" << endl; }

       fr.close();

    }

    else

    {      cout << "打开文件失败!\n" << endl; }

}

三、测试与结论

1、测试环境与数据

   1. 测试环境:Visual Studio 2019

   2. 测试数据:

学号

姓名

物理

数学

历史

OOP

英语

1

a

89

90.5

86

49

65

2

b

38

49

89

99

76.5

3

c

49.5

99.5

59

47

90

2、测试用例

  1.数据输入
1)手动输入如图1

1 手动输入成绩

2)从文件读取如图2


2 读取成绩

2.信息添加和删除后输出如图3


 

3 添加、删除成绩

3.信息修改如图4


 

4 修改成绩

4.信息查询输出如图5

5 查询信息

5.成绩按原顺序或排名输出如图6,成绩相同时按学号如图7

6 按顺序输出成绩


7 相同分数排序

6.保存文件如图8

8 保存文件

7.成绩分析,获得包括成绩分布、最高分、最低分和平均分等信息如图9


 

9 分析成绩

8.程序容错:文件打开失败,未查找到对应学生信息如图10,无学生信息时提示错误如图11,输入重复信息提示如图12


10

11


12

3、测试结论

经过测试,代码圆满完成了题目的各项要求,实现了数据的输入、输出、修改、排序、统计和存储。

源代码网址:(1条消息) 基于C++语言的学生成绩管理程序(链表)-C/C++文档类资源-CSDN文库

  • 4
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

where_are_u

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

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

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

打赏作者

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

抵扣说明:

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

余额充值