欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

单链表实现学生成绩管理系统的增删改查

程序员文章站 2022-05-06 18:05:14
...

写在前面:这个代码除了实现基本的数据增删改查外,还对数据进行了按学号排序输入,输出到文档中!同时对界面实现了优化!对数据插入方法使用插入排序!以及人数的统计,多种查询方式等!代码是很久之前写的,当时刚好学了单链表这一块,最近碰巧在磁盘里看到了就把它发了出来,顺便把文件操作内容补充了!

//全局定义两个指针变量(头指针和尾指针);头指针用来遍历,尾指针用来添加Student成员;实现结果就不附图了,谢谢阅览!!!
//腾出一点时间顺便把文件处理内容也补充了,读者自行测试!!!!

#pragma warning(disable:4996)            //屏蔽某些非标准C库的警告!
//#define _CRT_SECURE_NO_WARNINGS            //防止scanf警告,也可直接用scanf_s;
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

//成绩表结构体
typedef struct stu
{
    long num;
    char name[10];
    char sex[4];
    float Math;
    float Chinese;
    float English;
    struct stu* next;
}STU;

FILE *fp;
char filename[20];
STU* Head = NULL;  //定义一个指针
STU* End = NULL;   //尾结点

//创建头结点和尾结点
void CreatList()
{
    Head = (struct stu*)malloc(sizeof(struct stu));
    Head->next = NULL;  
    STU* End = Head;    
}

//文件加载
void LoadData()
{
    CreatList();
    STU* ptr;
    printf("\n\n\n\n        请输入文件名:");
    scanf("%s", filename);
    if ((fp = fopen(filename, "a+")) == NULL)
    {
        printf("\n                Error!!!");
        printf("\n                Error!!!");
        printf("\n                Error!!!");
        printf("\n              文件打开失败!!!");
        exit(0);
    }
    ptr = (struct stu*)malloc(sizeof(struct stu));
    ptr->next = NULL;
    while (fscanf(fp, "%ld  %s  %s  %f  %f  %f\n", &ptr->num, ptr->name, ptr->sex, &ptr->Math, &ptr->Chinese, &ptr->English) != EOF)
    {
        if (Head->next == NULL)
        {
            Head->next = ptr;
            End = ptr;
        }
        else
        {
            End->next = ptr;
            End = End->next;
        }
        ptr = (struct stu*)malloc(sizeof(struct stu));
        ptr->next = NULL;
    }
    free(ptr);       
    fclose(fp);
}


//写入数据到文件中,并保存文件
void SaveData()
{
    STU* ptr = Head->next;
    if ((fp = fopen(filename, "w")) == NULL)
    {
        printf("\n                Error!!!");
        printf("\n                Error!!!");
        printf("\n                Error!!!");
        printf("\n              文件打开失败!!!");
        exit(0);
    }
    while (ptr != NULL)
    {
        fprintf(fp, "%ld  %s  %s  %6.2f  %6.2f  %6.2f\n", ptr->num, ptr->name, ptr->sex, ptr->Math, ptr->Chinese, ptr->English);
        ptr = ptr->next;
    }
    fclose(fp);
}

//添加学生成绩信息
void AddStudent()
{
    int n, i;
    printf("\n请输入您要添加的学生人数:");
    scanf("%d", &n);
    for (i = 0; i<n; i++)
    {
        struct stu* pNew = (struct stu*)malloc(sizeof(struct stu));
        if (pNew == NULL)
        {
            printf("\n               空间分配失败,程序异常终止!!!\n\n");
            exit(-1);
        }
        pNew->next = NULL;
        printf("\n            要添加的第%d个学生的信息如下:\n", i + 1);
        printf("\n请输入第%d个学生学号: ", i + 1);
        scanf("%ld", &pNew->num);

        //检查学号是否重复
        STU* temp = Head->next;
        while (temp != NULL)
        {
            if (temp->num == pNew->num)
            {
                printf("\n              学号重复,请重新输入!!!\n");
                printf("\n请重新输入第%d个学生学号: ", i + 1);
                scanf("%ld", &pNew->num);
                temp = Head->next;        //重新遍历比较
                continue;
            }
            else
                temp = temp->next;
        }
        printf("请输入第%d个学生姓名: ", i + 1);
        scanf("%s", pNew->name);
        printf("请输入第%d个学生性别: ", i + 1);
        scanf("%s", pNew->sex);
        printf("请输入第%d个学生数学成绩: ", i + 1);
        scanf("%f", &pNew->Math);
        while (1)
        {
            if ((pNew->Math)< 0 || (pNew->Math > 100))
            {
                printf("\n            输入成绩有误,请检查!!!\n");
                printf("\n请重新输入第%d个学生数学成绩: ", i + 1);
                scanf("%f", &pNew->Math);
            }
            else break;
        }
        printf("请输入第%d个学生语文成绩: ", i + 1);
        scanf("%f", &pNew->Chinese);
        while (1)
        {
            if ((pNew->Chinese)< 0 || (pNew->Chinese > 100))
            {
                printf("\n            输入成绩有误,请检查!!!\n");
                printf("\n请重新输入第%d个学生语文成绩: ", i + 1);
                scanf("%f", &pNew->Chinese);
            }
            else break;
        }
        printf("请输入第%d个学生英语成绩: ", i + 1);
        scanf("%f", &pNew->English);
        while (1)
        {
            if ((pNew->English)< 0 || (pNew->English) > 100)
            {
                printf("\n            输入成绩有误,请检查!!!\n");
                printf("\n请重新输入第%d个学生英语成绩: ", i + 1);
                scanf("%f", &pNew->English);
            }
            else break;
        }

        //按学号排序,边添加边排序;
        if (Head->next == NULL)
        {
            Head->next = pNew;        //作为首元素
            End = Head->next;
            //End->next = NULL;
        }
        else
        {
            if (pNew->num > End->num)
            {
                End->next = pNew;
                End = End->next;
                //End->next = NULL;
            }
            else
            {
                STU* p1 = Head->next;
                if (pNew->num > p1->num)        //表明链表中已经至少存在2个成员(至少存在首和尾);
                {
                    STU* p2 = p1->next;
                    while (1)
                    {
                        if ((pNew->num > p1->num) && (pNew->num < p2->num))
                        {
                            pNew->next = p2;
                            p1->next = pNew;
                            break;
                        }
                        else
                        {
                            p1 = p1->next;
                            p2 = p2->next;
                        }
                    }

                }
                else
                {
                    pNew->next = p1;
                    Head->next = pNew;
                }

            }
        }
    }
    printf("\n\n             学生信息全部添加完成!!!\n");
}

//通过前驱结点删除学生成绩信息
void DeleteStudent()
{
    int num;
    printf("\n请输入您要删除的学生的学号:");
    scanf("%ld", &num);
    STU* pre = Head;        //表中没有数据时,pre为空;

    while (1)
    {
        if (pre->next && (pre->next->num == num))
        {
            STU* q = pre->next;
            pre->next = pre->next->next;
            //pre->next = NULL;
            printf("\n\n                删除操作成功!!!\n");
            printf("\n             已删除的学生成绩信息如下!!!\n\n");
            printf("学号\t\t姓名\t性别\t数学\t语文\t英语\t\n\n");
            printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", q->num, q->name, q->sex, q->Math, q->Chinese, q->English);
            free(q);
            return;
        }
        else
        {
            if (pre->next != NULL)
                pre = pre->next;
            else
            {
                printf("\n\n                信息删除失败!!!\n");
                return;
            }
        }
    }

    //寻找前驱结点的第二种方法
    /*
    while (pre->next && (pre->next->num != num))
    pre = pre->next;
    if (pre->next)            //pre为前驱
    {
    STU* q = pre->next;
    pre->next = pre->next->next;
    //pre->next = NULL;
    printf("\n\n                删除操作成功!!!\n");
    printf("\n             已删除的学生成绩信息如下!!!\n\n");
    printf("学号\t\t姓名\t性别\t数学\t语文\t英语\t\n\n");
    printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", q->num, q->name, q->sex, q->Math, q->Chinese, q->English);
    free(q);
    }
    else
    printf("\n\n                信息删除失败!!!\n");
    */

}


//更改学生成绩信息
void AlterStudent()
{
    int num;
    printf("\n请输入您要更改学生的学号:");
    scanf("%ld", &num);
    STU* change = Head->next;
    while (change && (change->num != num))
        change = change->next;
    if (change)
    {
        printf("\n更改后的学号:");
        scanf("%ld", &change->num);
        printf("\n更改后的姓名: ");
        scanf("%s", change->name);
        printf("\n更改后的性别: ");
        scanf("%s", change->sex);
        printf("\n更改后的数学成绩: ");
        scanf("%f", &change->Math);
        printf("\n更改后的语文成绩: ");
        scanf("%f", &change->Chinese);
        printf("\n更改后的英语成绩: ");
        scanf("%f", &change->English);
        printf("\n\n            学生信息已经更改完毕!!!\n");
    }
    else
        printf("\n\n            学生信息不存在,无法更改!!!\n");
}

//查询学生成绩信息
void SeekStudent()
{
    while (1)
    {
        printf("\n\n请选择查询方式??? 按学号:1 / 按姓名:2:  ");
        int k;
        scanf("%d", &k);
        switch (k)
        {
        case 1:
        {
                  int num;
                  printf("\n请输入您要查找学生的学号:");
                  scanf("%ld", &num);
                  STU* find = Head->next;
                  while (find && (find->num != num))
                      find = find->next;
                  if (find)
                  {
                      printf("\n查询学生信息如下:\n\n");
                      printf("学号\t\t姓名\t性别\t数学\t语文\t英语\n\n");
                      printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", find->num, find->name, find->sex, find->Math, find->Chinese, find->English);
                  }
                  else
                      printf("\n\n            没有查询到该学生信息!!!\n");
                  return;

        }
        case 2:
        {
                  printf("\n请输入您要查找学生的姓名:");
                  char name1[20];
                  scanf("%s", name1);
                  STU* find = Head->next;
                  while (find && (strcmp(find->name, name1) != 0))
                      find = find->next;
                  if (find)
                  {
                      printf("\n查询学生信息如下:\n\n");
                      printf("学号\t\t姓名\t性别\t数学\t语文\t英语\n\n");
                      printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", find->num, find->name, find->sex, find->Math, find->Chinese, find->English);
                  }
                  else
                      printf("\n\n            没有查询到该学生信息!!!\n");
                  return;
        }
        default:
        {
                   printf("\n\n查询方式错误!!! 请重新选择查询方式\n");
                   break;
        }
        }
    }
}


//输出全部学生成绩
void DisplayAll()
{
    STU* p = Head->next;
    int len = 0;
    printf("\n                全部学生成绩信息如下!!!\n\n");
    printf("学号\t\t姓名\t性别\t数学\t语文\t英语\n\n");
    while (p != NULL)
    {
        printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", p->num, p->name, p->sex, p->Math, p->Chinese, p->English);
        p = p->next;
        len++;
        while (p == NULL)
        {
            printf("\n\n               成绩系统含学生总人数为:%d 人\n", len);
            return;
        }
    }
    printf("\n                Error!!!");
    printf("\n                Error!!!");
    printf("\n                Error!!!");
    printf("\n              成绩表中数据为空!!!\n");
    return;
}

//视图界面
void VeiwInterface()
{
    system("cls");
    printf("   \t***********************************************************\n");
    printf("   \t*        欢迎使用学生成绩管理系统            *\n");
    printf("   \t***********************************************************\n\n");
    printf("   \t*|*\t\t   1.添加学生成绩信息   \t\t*|*\n\n");
    printf("   \t*|*\t\t   2.删除学生成绩信息   \t\t*|*\n\n");
    printf("   \t*|*\t\t   3.更改学生成绩信息   \t\t*|*\n\n");
    printf("   \t*|*\t\t   4.查询学生成绩信息   \t\t*|*\n\n");
    printf("   \t*|*\t\t   5.输出全部学生信息   \t\t*|*\n\n");
    printf("   \t*|*\t\t   6.--- 退出系统 ---   \t\t*|*\n\n");
    printf("   \t*-*-----------------------------------------------------*-*\n");
    printf("\n请选择功能??? 输入序号:<1--6>:");
}

//需要执行的功能选择
void ChoiceFunction(int k)
{
    while (1)
    {
        switch (k)
        {
        case 1:
        {
                  while (1)
                  {
                      system("cls");
                      AddStudent();
                      printf("\n\n是/否继续添加学生成绩信息??? 继续:1 / 退出:0:  ");
                      int select1 = getch() - 48;
                      switch (select1)
                      {
                      case 1: break;
                      case 0: return;
                      default:
                      {
                                 printf("\n\n            输入错误!!! 按任意键回到主界面\n\n");
                                 system("pause");
                                 return;
                      }
                      }
                  }
        }

        case 2:
        {
                  while (1)
                  {
                      system("cls");
                      DeleteStudent();
                      printf("\n\n是/否继续删除学生成绩信息??? 继续:1 / 退出:0:  ");
                      int select2 = getch() - 48;
                      switch (select2)
                      {
                      case 1: break;
                      case 0: return;
                      default:
                      {
                                 printf("\n\n            输入错误!!! 按任意键回到主界面\n\n");
                                 system("pause");
                                 return;
                      }
                      }
                  }
        }

        case 3:
        {
                  while (1)
                  {
                      system("cls");
                      AlterStudent();
                      printf("\n\n是/否继续更改学生成绩信息??? 继续:1 / 退出:0:  ");
                      int select3 = getch() - 48;
                      switch (select3)
                      {
                      case 1: break;
                      case 0: return;
                      default:
                      {
                                 printf("\n\n            输入错误!!! 按任意键回到主界面\n\n");
                                 system("pause");
                                 return;
                      }
                      }
                  }
        }

        case 4:
        {
                  while (1)
                  {
                      system("cls");
                      SeekStudent();
                      printf("\n\n是/否继续查询学生成绩信息??? 继续:1 / 退出:0:  ");
                      int select4 = getch() - 48;
                      switch (select4)
                      {
                      case 1: break;
                      case 0: return;
                      default:
                      {
                                 printf("\n\n            输入错误!!! 按任意键回到主界面\n\n");
                                 system("pause");
                                 return;
                      }
                      }
                  }
        }

        case 5:
        {
                  while (1)
                  {
                      system("cls");
                      //system("color 17");
                      DisplayAll();
                      printf("\n\n是/否退出显示??? 退出:1 / 刷新:0:  ");
                      int select5 = getch() - 48;
                      switch (select5)
                      {
                      case 1: return;
                      case 0: break;
                      default:
                      {
                                 printf("\n\n            输入错误!!! 按任意键回到主界面\n\n");
                                 system("pause");
                                 return;
                      }
                      }
                  }
        }

        case 6:
        {
                  SaveData();
                  printf("\n\n再次确认是/否退出系统??? 退出:1 / 取消:0:  ");
                  int select6 = getch() - 48;
                  switch (select6)
                  {
                  case 1: exit(0);
                  case 0: return;
                  default: return;
                  }
        }

        default:
        {
                   printf("\n\n            输入错误!!! 按任意键回到主界面重新选择\n\n");
                   system("pause");
                   return;
        }
        }
    }
}

//主函数
void main()
{
    LoadData();
    int key;
    while (1)
    {
        VeiwInterface();
        key = getch() - 48;        //返回的是字符的ASCLL值,‘1’= 49.....;
        ChoiceFunction(key);
    }
}

添加成员

单链表实现学生成绩管理系统的增删改查

 

显示输出:

 

单链表实现学生成绩管理系统的增删改查

查找学员:

单链表实现学生成绩管理系统的增删改查

更改学员:

单链表实现学生成绩管理系统的增删改查

删除学员:

单链表实现学生成绩管理系统的增删改查

显示输出:

单链表实现学生成绩管理系统的增删改查

此外对于存入文件中,博主在这里没有直接给出代码,读者可以自行设计(用文件指针实现),不理解的地方可以留言一起讨论,谢谢指教!

补充:前几天把文件处理内容补充了,今天把代码发了上来,可以试着用“feof”去代替我的“EOF”,看看结果怎样!!!!