【原创】单链表实战学生成绩管理系统

blogdaren 2021-01-09 抢沙发 39人次

问题背景:

通过单链表实战学生成绩管理系统,涉及到的知识点比较广泛(仅关注原理、业务逻辑校验细节未关注):

单链表自身、结构体、指针、位操作、趣味宏、堆内存、排序算法等等。

先看效果图:

11.jpg

22.jpg

33.jpg

44.jpg

实现代码:

/*
 * =====================================================================================
 *
 *       Filename:  student.c
 *
 *    Description:  大学生成绩管理系统
 *
 *        Version:  1.0
 *        Created:  2021年01月08日 23时04分42秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  blogdaren
 *   Organization:  www.phpcreeper.com
 *
 * =====================================================================================
 */
#include <stdio.h>
#include <stdlib.h>
#include "./myinclude/global.h"

//以下宏以及各种声明在标准化编程时应当移植到独立的student.h头文件
#define SUCCESS 0
#define FAILURE 1
#define LIST_FLAG_INITIALIZED      (1<<0)
#define MAX_NUMBER_OF_SPECIAL_CHAR  58
#define DO_WHILE_START  do{
#define DO_WHILE_END    }while(8 != command);
#define GET_AVG_SCORE(x1, x2, x3) ((x1) + (x2) + (x3)) / 3
#define COPY_DATA(p1, p2) \
        do  \
        {   \
            strcpy((p1)->data.name, (p2)->name); \
            (p1)->data.yuwen_score  = (p2)->yuwen_score; \
            (p1)->data.shuxue_score = (p2)->shuxue_score; \
            (p1)->data.yingyu_score = (p2)->yingyu_score; \
            (p1)->data.avg_score = GET_AVG_SCORE( \
                    (p2)->yuwen_score, \
                    (p2)->shuxue_score, \
                    (p2)->yingyu_score \
            ); \
        }while(0); \     

struct student
{
    char  name[20];
    float yuwen_score;
    float shuxue_score;
    float yingyu_score;
    float avg_score;
};
typedef struct student Item;

typedef struct node
{
    Item data;
    struct node *next;
}Node;

typedef struct list
{
    Node *head;
    int total;
    int flags;
}List;


void showWelcome();
void showTableTitle();
Node *createNode(List *plist, Item *pitem);
Node *deleteNode(List *plist, char *name);
Node *modifyNode(List *plist, char *name);
void freeNode(List *plist);
void showListData(List *plist);
void initListData(List *plist);
int  countListData(List *plist);
Node *searchListData(List *plist, char *name);
void sortListData(List *plist);
void showSortedListData(List *plist);

int main()
{
    int result, i, command;
    char tname[20];
    Node *tmp;
    List mylist, *plist;
    Item item, *pitem;
    plist = &mylist;
    pitem = &item;

    showWelcome();
    initListData(plist);

    i = 0;
    DO_WHILE_START
        printf("\n--> 请输入一个有效数字指令:");
        result = scanf("%d", &command);
        /*printf("%d-%d\n", result, command);*/
        if(result != 1) scanf("%*[^\n]");
        if(command < 1 || command > 8) continue;

        switch(command)
        {
            case 1:
                showWelcome();
                break;
            case 2:
                i++;
                printf("请输入第(%02d)个学生的真实姓名:", i);
                scanf("%s", item.name);
                printf("请输入第(%02d)个学生的语文成绩:", i);
                scanf("%f", &item.yuwen_score);
                printf("请输入第(%02d)个学生的数学成绩:", i);
                scanf("%f", &item.shuxue_score);
                printf("请输入第(%02d)个学生的英语成绩:", i);
                scanf("%f", &item.yingyu_score);
                createNode(plist, pitem);
                break;
            case 3:
                printf("--> 请输入待删除成绩的学生姓名:");
                scanf("%s", tname);
                tmp = deleteNode(plist, tname);

                if(NULL == tmp)
                    printf("<-- 没有找到要删除的记录!!!");
                else
                    printf("<-- 嘿嘿记录已经成功删除!!!");

                break;
            case 4:
                printf("--> 请输入待修改成绩的学生姓名:");
                scanf("%s", tname);
                tmp = modifyNode(plist, tname);
                break;
            case 5:
                showListData(plist);
                break;
            case 6:
                showSortedListData(plist);
                break;
            case 7:
                system("clear");
                break;
            case 8:
                freeNode(plist);
                printf("<-- Bye!! See You Next Time!!\n");
                break;
            default:
                break;
        }
    DO_WHILE_END

    return 0;
}

void initListData(List *plist)
{
    if(plist->flags & LIST_FLAG_INITIALIZED) return;

    plist->head = NULL;
    plist->total = 0;
    plist->flags |= LIST_FLAG_INITIALIZED;
}

int countListData(List *plist)
{
    return plist->total;
}

Node *createNode(List *plist, Item *pitem)
{
    Node *pnode, *pnew;

    if(countListData(plist) == 0)
    {
        plist->head = pnode = (Node *)malloc(sizeof(Node));

        if(pnode == NULL) 
        {
            printf("malloc failed\n");
            exit(FAILURE);
        }

        plist->total++;
        COPY_DATA(pnode, pitem);
        pnode->next = NULL;

        return pnode;
    }

    pnode = plist->head;

    while(pnode->next != NULL)
    {
        pnode = pnode->next;
    }

    pnew = (Node *)malloc(sizeof(Node));
    COPY_DATA(pnew, pitem);
    pnew->next = NULL;
    pnode->next = pnew;
    plist->total++;

    return pnode;
}


void showListData(List *plist)
{
    Node *pnode;

    if(countListData(plist) == 0)
    {
        printf("<-- 列表中空空如也!!!");
        return;
    }

    pnode = plist->head;
    showTableTitle();

    while(pnode != NULL)
    {
        printf("‖  %-11s‖ %-9.2f‖ %-9.2f‖ %-9.2f‖ %-9.2f‖\n", pnode->data.name, 
                pnode->data.yuwen_score, 
                pnode->data.shuxue_score,
                pnode->data.yingyu_score,
                pnode->data.avg_score
        );
        echoRepeatString("=", MAX_NUMBER_OF_SPECIAL_CHAR);
        pnode = pnode->next;
    }

    printf("‖                     总共 %d 条记录                       ‖\n", countListData(plist));
    echoRepeatString("=", MAX_NUMBER_OF_SPECIAL_CHAR);
}

void freeNode(List *plist)
{
    Node *pnode;
    pnode = plist->head;

    while(pnode != NULL)
    {
        free(pnode);
        printf("<-- 成功释放节点 (%p)\n", pnode);
        pnode = pnode->next;
    }

    plist->head  = NULL;
    plist->total = 0;
}


Node *deleteNode(List *plist, char *name)
{
    Node *phead, *pnode, *tmp = NULL;
    phead = pnode = plist->head;

    tmp = searchListData(plist, name);
    if(NULL == tmp) return NULL;

    //如果删除的是头指针
    if(phead == tmp)
    {
        plist->head = tmp->next;
        free(tmp);
        plist->total--;

        return phead;
    }

    //否则删除的必定是后续某个指针
    while(pnode->next != tmp)
    {
        pnode = pnode->next;
    }
    
    pnode->next = tmp->next;
    free(tmp);
    plist->total--;

    return tmp;
}

Node *modifyNode(List *plist, char *name)
{
    Node *tmp = NULL;
    Item item2, *pitem2;
    pitem2 = &item2;

    tmp = searchListData(plist, name);
    if(NULL == tmp) return NULL;

    strcpy(item2.name, name);

    printf("请输入该学生修正后的语文成绩:");
    scanf("%f", &item2.yuwen_score);
    printf("请输入该学生修正后的数学成绩:");
    scanf("%f", &item2.shuxue_score);
    printf("请输入该学生修正后的英语成绩:");
    scanf("%f", &item2.yingyu_score);

    COPY_DATA(tmp, pitem2);
}

Node *searchListData(List *plist, char *name)
{
    Node *pnode;

    if(countListData(plist) == 0) return NULL;

    pnode = plist->head;

    while(pnode != NULL)
    {
        if(strcmp(pnode->data.name, name) == 0)
        {
            return pnode;
        }

        pnode = pnode->next;
    }

    return NULL;
}

void showWelcome()
{
    putchar('\n');
    puts("============================================");
    puts("‖  单链表实战学生成绩管理系统,指令如下:  ‖");
    puts("============================================");
    puts("‖         1. 显示帮助界面                  ‖");
    puts("‖         2. 新增一条学生成绩              ‖");
    puts("‖         3. 根据姓名删除学生成绩          ‖");
    puts("‖         4. 根据姓名修改学生成绩          ‖");
    puts("‖         5. 查看班级所有学生成绩          ‖");
    puts("‖         6. 按照平均成绩降序展示          ‖");
    puts("‖         7. 清理当前屏幕                  ‖");
    puts("‖         8. 退出当前程序                  ‖");
    puts("============================================");
}

void showTableTitle()
{
    echoRepeatString("=", MAX_NUMBER_OF_SPECIAL_CHAR);
    printf(
        "‖  %s   ‖ %s ‖ %s ‖ %s ‖ %s", 
        "学生姓名", "语文成绩", "数学成绩", "英语成绩", "平均成绩 ‖\n"
    ); 
    echoRepeatString("=", MAX_NUMBER_OF_SPECIAL_CHAR);
}

void sortListData(List *plist)
{
    int i, total;
    Node *current, *after;
    Item tmpdata;

    total = countListData(plist);
    if(total <= 0) return;

    while(total > 0)
    {
        current = plist->head;
        after = current->next;

        for(i = 0; i < total; i++)
        {
            if(after == NULL) break;

            if(current->data.avg_score < after->data.avg_score)
            {
                strcpy(tmpdata.name, after->data.name);
                tmpdata.yuwen_score  = after->data.yuwen_score;
                tmpdata.shuxue_score = after->data.shuxue_score;
                tmpdata.yingyu_score = after->data.yingyu_score;
                tmpdata.avg_score    = after->data.avg_score;

                strcpy(after->data.name, current->data.name);
                after->data.yuwen_score  = current->data.yuwen_score;
                after->data.shuxue_score = current->data.shuxue_score;
                after->data.yingyu_score = current->data.yingyu_score;
                after->data.avg_score    = current->data.avg_score;

                strcpy(current->data.name, tmpdata.name);
                current->data.yuwen_score  = tmpdata.yuwen_score;
                current->data.shuxue_score = tmpdata.shuxue_score;
                current->data.yingyu_score = tmpdata.yingyu_score;
                current->data.avg_score    = tmpdata.avg_score;
            }

            current = after;
            after = current->next;
        }

        total--;
    }

    printf("<-- 操作成功,按照平均成绩由高到低排列如下:\n");
}

void showSortedListData(List *plist)
{
    sortListData(plist);
    showListData(plist);
}


版权声明:除非注明,本文由( blogdaren )原创,转载请保留文章出处。

本文链接:【原创】单链表实战学生成绩管理系统

发表评论:

您的昵称:
电子邮件:
个人主页:

Free Web Hosting