c语言学生成绩管理系统5.0


#include<stdlib.h>
#include<string.h>
#include<stdio.h>
typedef struct course {//此结构体记录科目信息
    double coursescore;
}course;
typedef struct studentMessage {//此结构体记录学生信息
    char id[20];
    char name[20];
    double  score;
    double  averagescore;
    course* mycourse;
    studentMessage* pre;
    studentMessage* next;
}studentMessage;
char subject[10][10]; //科目的名字;
int subjectnum;//科目的数量
void ShowStudent(studentMessage stu);//输出单个学生的数据
void DepositStudent(studentMessage** begin);//传入学生
int  Length(studentMessage* begin);//返回链表的长度
void CaculateAllAndAverageScoreOfEveryStudent(studentMessage* begin);//单个学生的总分和平均分
void CaculateAllAndAverageScoreOfEveryCourse(studentMessage* begin);//单个科目总分和平均分
void DeleteOne(studentMessage* now, studentMessage** begin);//删除单个功能
void Delete(studentMessage* now, studentMessage** begin);//查找删除功能
void Swap(studentMessage* one, studentMessage* two);//交换两个结构体的数据,但是不交换里面的指针
bool BigToSmallcmp(studentMessage x, studentMessage y);//从大到小排序
bool SmallToBigcmp(studentMessage x, studentMessage y);//从小到大排序
bool IDCmp(studentMessage x, studentMessage y);//按照ID排序
bool NameCmp(studentMessage x, studentMessage y);//按照姓名排序
void Search(studentMessage* begin);//查找
void Sort(bool cmp(studentMessage pre, studentMessage next), studentMessage* begin, studentMessage* end, int bindex, int eindex);//快速排序
void StatisticAnalysis(studentMessage* begin);//统计等级
void CaculateAllAndAverageScore(studentMessage* begin);//统计平均分
void Cout(studentMessage* begin);//输出
void Display();//展示
studentMessage* studentlist=NULL;
studentMessage* studentlistend = NULL;
int main() {
    int choice;
    printf("请输入你要存储的考试科目个数:");
    scanf_s("%d", &subjectnum);
    getchar();
    for (int i = 0; i < subjectnum; i++) {
        printf("请输入第%d个科目名称:", i + 1);
        gets_s(subject[i]);
    }
    while (true) {
        Display();
        scanf_s("%d", &choice);
        switch (choice) {
        case 1:
            DepositStudent(&studentlist);//输入成绩
            break;
        case 2:
            CaculateAllAndAverageScoreOfEveryCourse(studentlist);//计算总分和平均分
            break;
        case 3:
            CaculateAllAndAverageScoreOfEveryStudent(studentlist);//计算每个人的总分和平均分
            break;
        case 4:
            Sort(BigToSmallcmp, studentlist, studentlistend, 0, Length(studentlist) - 1);//按照成绩由高到低排除名词表
            break;
        case 5:
            Sort(SmallToBigcmp, studentlist, studentlistend, 0, Length(studentlist) - 1);//按照成绩从小到大
            break;
        case 6:
            Sort(IDCmp, studentlist, studentlistend, 0, Length(studentlist) - 1);//按照学号从小到大
            break;
        case 7:
            Sort(NameCmp, studentlist, studentlistend, 0, Length(studentlist) - 1);//按照姓名排
            break;
        case 8:
            Search(studentlist);//按照学号查
            break;
        case 9:
            Search(studentlist);//按照姓名查
            break;
        case 10://等级统计
            StatisticAnalysis(studentlist);
            break;
        case 11://输出学生名单
            Cout(studentlist);
            break;
        case 12:
            Delete(studentlist, &studentlist);
        case 0://退出
            break;
        }
        system("pause");
        system("cls");
    }
}
void CaculateAllAndAverageScoreOfEveryStudent(studentMessage *begin) {
    if (begin == NULL)//判断是否存在数据
    {
        printf("请先存入学生");
        return;
    }
    studentMessage *now = begin;
    while (now != NULL) {//移动指针并且记录总和
        double sumscore=0;
        course* courseonw = now->mycourse;
        for (int i = 0; i < subjectnum; i++) {
            sumscore += (courseonw + i)->coursescore;
        }
        now->score = sumscore;
        now->averagescore = sumscore / subjectnum;
        now = now->next;
    }
    printf("计算完成\n");
}
void CaculateAllAndAverageScoreOfEveryCourse(studentMessage *begin) {
    if (begin == NULL)//判断是否存在数据
    {
        printf("请先存入学生");
        return;
    }
    studentMessage* now = begin;
    double allscore[10] = { 0 };
    while (now != NULL) {
        course *nowcourse = now->mycourse;
        for (int i = 0; i < subjectnum; i++) {
            allscore[i] += (nowcourse+i)->coursescore;    
        }
        now = now->next;
    }
    printf("总成绩:\n");
    for (int i = 0; i < subjectnum; i++) {
        printf("%s:%.1f\n", subject[i], allscore[i]);
    }
    printf("平均分:\n");
    for (int i = 0; i < subjectnum; i++) {
        printf("%s:%.1f\n", subject[i], allscore[i]/Length(begin));
    }
}
void Swap(studentMessage* one, studentMessage* two) {//交换两个节点,但是其内的pre和next不交换
    studentMessage temp = *one;
    *one = *two;
    *two = temp;
    two->pre = one->pre;
    two->next = one->next;
    one->pre = temp.pre;
    one->next = temp.next;

}
bool BigToSmallcmp(studentMessage x, studentMessage y)//从大到小排
{
    return x.score >= y.score;
}
bool SmallToBigcmp(studentMessage x, studentMessage y)//从小到大排
{
    return x.score <= y.score;
}
bool IDCmp(studentMessage x, studentMessage y)//ID从小到大排
{
    return strcmp(x.id ,y.id);
}
bool NameCmp(studentMessage x, studentMessage y)//按照姓名的字典序从小到大排
{
    return strcmp(x.name, y.name);
}
void Sort(bool cmp(studentMessage pre,studentMessage next),studentMessage *begin,studentMessage *end,int bindex,int eindex) {//快速排序
    studentMessage* b=begin;
    int bi = bindex;
    int ei = eindex;
    studentMessage* e=end;
    if (bi > ei) return;
    studentMessage* temp = begin;
    while (bi != ei) {
        while (cmp(*temp, *e) && ei > bi&&e!=NULL) {
            e = e->pre; 
            ei--;
        }
        while (cmp(*b, *temp) && ei > bi&&b!=NULL) {
            b = b->next;
            bi++;
        }
        if (ei > bi) {
            Swap(e, b);
        }
    }
    Swap(temp, b);
    Sort(cmp, begin, b->pre,bindex,bi-1);
    Sort(cmp, b->next, end,bi+1,eindex);
}
void StatisticAnalysis(studentMessage *begin) {
    int degree[10][5] = { 0 };
    int num = 0;
    studentMessage *now = begin;
    while (now != NULL) {
        for (int i = 0; i < subjectnum; i++) {
            if(((now->mycourse+i)->coursescore) >= 90)    {//+i表示第几门科目
                degree[i][0]++;
            }
            else if (now->score >= 80) {
                degree[i][1]++;
            }
            else if (now->score >= 70) {
                degree[i][2]++;
            }
            else if (now->score >= 60) {
                degree[i][3]++;
            }
            else {
                degree[i][4]++;
            }
        }        
        num++;
        now = now->next;
    }    
    for (int i = 0; i < subjectnum; i++) {
        printf("%4s 科目:\n",subject[i]);
        for (int j = 0; j < subjectnum; j++) {
            char mdegree = 'A';
            printf("%c:", mdegree+j);
            printf("%4.2f %% \n", degree[i][j] * 1.0 / num * 100);
        }
        
    }
}
void ShowStudent(studentMessage stu) {
    printf("ID:%5s  姓名:%5s   ", stu.id, stu.name);
    printf("总成绩:%4.1f 平均分:%4.1f ", stu.score, stu.averagescore);
    for (int i = 0; i < subjectnum; i++) {
        printf("%4s:%.1f", subject[i], (stu.mycourse + i)->coursescore);
    }
    printf("\n");
}
void Cout(studentMessage* begin) {
    studentMessage* now = begin;
    if (now == NULL) {
        printf("请先存入学生");
        return;
    }
    while (now != NULL) {
        ShowStudent(*now);
        now = now->next;
    }
}
void Search(studentMessage *begin) {
    getchar();
    int num=0;
    studentMessage* now = begin;
    char str[20];
    printf("请输入你要查询的学生的姓名或者学号:");
    gets_s(str);
    while (now != NULL) {
        if (strcmp(str, now->id) == 0|| strcmp(str, now->name) == 0) {
            ShowStudent(*now);
            num++;
        }
        now = now->next;
    }
    if (num == 0) {
        printf("查无此人\n");
    }
}
void DeleteOne(studentMessage* now,studentMessage **begin)//删除指定位置的节点
{
    if(now->pre != NULL)     now->pre->next = now->next;//如果待删除节点的前一个节点不为空,那么我们将前一个节点的下一个节点设为删除节点的下一个节点
    else *begin = now->next;//如果前一个节点为空 那么说明该节点位于表头 所以我们更改表头的位置为该节点的下一个节点
    if(now->next!=NULL) now->next->pre = now->pre;//如果待删除节点的下一个节点不为空,那么我们更改其前一个节点
    free(now->mycourse);//释放内存
    free(now);
}
void Delete(studentMessage* now,studentMessage **begin) //删除功能
{
    if (now == NULL)//判断是否存在数据
    {
        printf("请先存入学生");
        return;
    }
    getchar();
    char str[20];
    printf("请输入你要删除的学生的ID或者姓名");
    gets_s(str);
    while (now != NULL)//若当前节点为空那么停止操作
    {
        if (strcmp(now->id, str) == 0 || strcmp(now->name, str) == 0)//如果有符合的那么我们输出并且返回 
        {
            DeleteOne(now, begin);
            printf("删除成功\n");
            return;
        }
        now = now->next;
    }
    printf("没有找到\n");

}
int Length(studentMessage* begin)//返回链表长度
{
    studentMessage* now = begin;
    int len= 0;
    if (begin == NULL) {
        return len;
    }
    while (true) {
        len++;
        if (now->next == NULL) {
            return len;
        }
        now = now->next;
    }
}
void CaculateAllAndAverageScore(studentMessage* now) {
    double scoresum = 0;
    if (now == NULL) {
        printf("请先存入学生");
        return;
    }
    studentMessage* begin = now;
    while (true) {
        scoresum +=now->score;
        if (now->next== NULL) {
            break;
        }
        now = now->next;
    }
    printf("总分是:%.1f\n", scoresum);
    printf("平均分是:%.2f\n", scoresum/Length(begin));
}
void SetNow(studentMessage** now, char id[], char name[], double *score, studentMessage* pre, studentMessage** anthor)//新建一个
{
    *now = (studentMessage*)malloc(sizeof(studentMessage));//给指针分配内存
    if (*anthor == NULL) {//判断锚点是否为空,也就是我们的链表是否已经存在数据
        *anthor = *now;//如果不存在数据那我们将新分配的内存作为链表锚点的起始点
    }
    (*now)->pre = pre;//前一个节点的设立
    (*now)->next = NULL;//后一个节点置空
    strcpy_s((*now)->name, name);//复制节点的内容
    strcpy_s((*now)->id, id);
    (*now)->mycourse = (course*)malloc(subjectnum*sizeof(course));
    course* anth = (*now)->mycourse;
    for (int i = 0; i < subjectnum; i++) {
        (*now)->mycourse->coursescore = score[i];
        ((*now)->mycourse)++;
    }
    (*now)->mycourse =anth;//将移动的指针归位
}
void DepositStudent(studentMessage **now)//添加学生,使用**是为了为*指针分配新的内存空间
 { 
    double thescore[10] = { 0 };
    int num;//记录要存储的学生的数目
    printf("请输你要存储的学生人数:");
    scanf_s("%d", &num);
    printf("\n");
    studentMessage* anthor=NULL;//相当于锚点,记录下链表头,因为在后序添加中会使得表头的位置发生改变
    studentMessage** begin = now;//表示当前正在访问的
    studentMessage** pre=now;//用作链表的前一个结构体的添加
    if (*begin != NULL)//判断是否已经存在数据
    {
        anthor = *now;//如果存在那么记录表头
        while (*begin!= NULL)//使得begin中记录的指针地址发生改变,直到遇到空指针。 
        {
            begin = &((*begin)->next);//begin记录的是指针的地址
            if (*begin == NULL)//如果*begin为空那么我们直接中止,此时pre记录的指针是该空指针的前一个 
            {
                break;
            }
            *pre = *begin;
        }
    }
    else {
        *pre = NULL;//如果不存在数据那么从表头添加数据,前一个当然为空
    }
    for (int i = 0; i < num; i++)//进行数据添加 
    {
        printf("当前存储的是第%d个学生",i+1);
        char id[20];
        char name[20];
        getchar();
        printf("id:");
        gets_s(id);
        printf("姓名:");
        gets_s(name);
        for (int j = 0; j < subjectnum; j++) {
            printf("%4s成绩:", subject[j]);
            scanf_s("%lf", &thescore[j]);
            printf("\n");
        }
        SetNow(begin, id, name, thescore, *pre,&anthor);//分配新的地址
        studentlistend = *begin;//studentlistend记录的是表尾的地址,我们在快排中会用到
        pre = begin;//将pre向前移
        begin= &((*begin)->next);//将begin向前移
    }
    *now = anthor;//将表头归位
}
void Display()//功能的展示 
{
    printf("1.Input record\n"
        "2.Caculate total and average score of every course\n"
        "3.Caculate total and average score of every student\n"
        "4.Sort in descending order by score\n"
        "5.Sort in ascending order by score\n"
        "6.Sort in ascending order by ID\n"
        "7.Sort in dictionary order by name\n"
        "8.Search by number\n"
        "9.Search by name\n"
        "10.Statistic analysis\n"
        "11.List record\n"
        "12.Delete Student\n"
        "0.Exit\n"
        "Please enter your choise:"
    );
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值