精华内容
下载资源
问答
  • 在《C语言学生信息管理系统演示和说明(密码版)》一节中,我们对学生信息管理系统进行了介绍和演示,这节就来分析一下它源码。学生信息管理系统源码下载地址... 整体设计思路要想持久化地保存数据,必须要将数据写...

    在《C语言学生信息管理系统演示和说明(密码版)》一节中,我们对学生信息管理系统进行了介绍和演示,这节就来分析一下它的源码。学生信息管理系统源码下载地址:http://pan.baidu.com/s/1pKjMVij    提取密码:s2ki各位读者不妨先将源码下载下来浏览一遍,记住关键的几个函数,整理一下不了解的知识点,做到心中有数。

    一. 整体设计思路

    要想持久化地保存数据,必须要将数据写入磁盘中;本程序也不例外,我们会将学生信息最终都保存到文件中。在《C语言学生信息管理系统源码下载和思路解析(文件版)》一节中我们看到,直接对文件数据进行增删改查操作不仅麻烦,而且低效,所以我们引入了数据结构中的单链表。当对学生信息进行插入、删除、修改操作时,我们需要先更新单链表,再将单链表中的所有数据(包括未修改的数据)更新到文件。如此,对文件进行的就是整体操作,就简单很多,可以先将文件内容清除,再写入新的数据。需要注意的是:只能将节点中的数据写入文件,不能将 next 节点的指针写入。例如:

    typedef struct _NODE{

    STU data;

    struct _NODE *next;

    }NODE;

    只需要将成员 data 写入文件,而不能写入 next。这是因为,next 是指针,指向内存中的某个位置,程序重新启动时,它的内存布局和上次肯定不同,next 的指向也会发生改变,所以每次启动程序时都必须读取文件中的数据新建单链表,存储 next 是没有意义的。注意:数据在写入文件前要先进行加密,读取后也要先进行解密才能使用。

    二. 关键知识点

    大家需要先学习一下该程序中涉及到的几个关键知识点,有了这些必备条件,我们才能更容易理解代码。

    1) 模块化编程

    本程序的代码比较多,总共有670多行,需要分门别类、有规划地放到不同的源文件中,这就是所谓的模块化编程(也即多文件编程)。在模块化编程中,需要在 .c 文件中定义函数,在 .h 中声明函数、变量、自定义类型、结构体、宏等,请大家猛击《C语言多文件编程》一章了解详情。

    2) 循环菜单

    程序运行时,会不停地显示主菜单和子菜单,而不是执行完一次操作就退出,这是如何实现的呢?请大家猛击《C语言循环菜单的设计,让程序一直运行》了解详情。

    3) 单链表

    大家在阅读代码之前,需要对数据结构中的单链表有所了解,知道如何对节点信息进行增删改查。

    4) 数据的加密解密

    数据的加密方式有很多,这里我们使用一种相对简单的方式,就是异或运算,这在《C语言文件加密的原理--异或运算》一节中进行了详细讲解。

    5) MD5

    用于对数据加密解密的密码也得保存在文件中,否则下次使用时就无法判断用户输入的密码是否正确。但是,直接将密码保存到文件中是非常危险的,这无疑是将密码告诉了他人。为了避免这种情况,我们还需要对密码本身进行加密。用于对密码加密的算法有多种,MD5算法是常用的一种。本程序也使用MD5算法。不管密码有多长,包含什么字符,经过MD5算法处理后都会变成一个由数字和字母组成的字符串,并且这个字符串的长度始终是32。例如,123456 经MD5加密后的结果是:

    e10adc3949ba59abbe56e057f20f883e

    MD5算法具有唯一性和不可逆性,也就是说:

    • 同一个密码加密后的字符串始终是相同的;

    • 通过加密后的字符串不能逆向推算出原来的密码。

    对密码进行MD5运算后,将得到的长度为32的字符串保存到文件中就非常安全了,即使被他人看到,也不知道密码是什么。

    三. 程序的整体架构

    程序由8个文件构成,其中包括4个头文件(.h)和4个源文件(.c)。1) main.c 是主文件,包含了主函数 main() 以及两个打印菜单的函数 printMainMenu()、printSubMain()。2) common.h 是程序的配置文件,每个文件都应该将它包含进去。配置文件中主要是宏定义,每一个宏都是一个配置选项,用户可以更改。例如:

    • FILENAME 宏定义了数据文件的路径,也就是将学生信息保存到何处,默认是当前目录下的 stu.data。如果你希望将文件放在其他目录下,完全可以改成诸如D:\\Demo\stu.dataC:\\data.stu的形式。

    • MAX_STU_AGE 宏定义了学生的最大年龄,如果用户输入的年龄大于该值,就会给出提示。

    3) tools.c 和 tools.h 主要提供了工具类函数。所谓工具类函数,也就是通用函数,它们不针对具体程序编写,可以用在当前程序中,也可以用在其他程序中,在移植的过程中一般不需要修改代码。4) stu.c 和 stu.h 是主要的两个文件,包含了对学生信息进行增删改查的函数。5) md5.c 和 md5.h 是MD5算法的源文件和头文件。大家不必理解MD5算法是如何实现的,阅读源代码时可以将这两个文件跳过,只要知道 MD5() 函数如何使用就可以。下面是MD5()函数的原型:

    void MD5(unsigned char *original, unsigned char cipher[33]);

    original 是要加密的数据,cipher 是加密后的数据。cipher 的长度之所以为 33,而不是32,是因为在最后要添加字符串结束标志 \0。

    四. 密码的保存以及数据的加密

    本程序中,我们将MD5加密后的密码保存在文件的开头,占用32个字节。也就是说,从第33个字节才开始,存储的才是学生信息。不妨将原始密码称为 pwd,将一次MD5加密后的密码称为 pwdMD5。我们可以把 pwdMD5 保存在文件开头,并用 pwd 对文件数据(学生信息)进行加密。程序运行后,读取用户输入的密码 pwd,然后进行MD5运算得到 pwdMD5,将 pwdMD5 与文件前32字节进行比较就知道用户输入的密码是否正确。如果密码正确,就用 pwd 对学生信息进行解密,否则提示用户密码错误。

    0b03a6577394ad6e2f2ecdf7b13651c9.png

    展开全文
  • 在《C语言学生信息管理系统演示和说明(文件版)》一节中,我们对学生信息管理系统进行了介绍和演示,这节就来分析一下它源码。学生信息管理系统源码下载... 整体设计思路要想持久化地保存数据,必须要将数据写入磁...

    在《C语言学生信息管理系统演示和说明(文件版)》一节中,我们对学生信息管理系统进行了介绍和演示,这节就来分析一下它的源码。学生信息管理系统源码下载地址:http://pan.baidu.com/s/1hqZRiDY    密码:ty9f各位读者不妨先将源码下载下来浏览一遍,记住关键的几个函数,整理一下不了解的知识点,做到心中有数。

    一. 整体设计思路

    要想持久化地保存数据,必须要将数据写入磁盘中;本程序也不例外,我们会将学生信息最终都保存到文件中。当增加、删除、修改学生信息时,我们也应该对文件做出同样的操作。这就是本节的重点:

    • 如何检索文件;

    • 如何在文件中插入数据;

    • 如何删除文件中的部分数据;

    • 如何修改文件中的数据。

    二. 关键知识点

    大家需要先学习一下该程序中涉及到的几个关键知识点,有了这些必备条件,我们才能更容易理解代码。

    1) 模块化编程

    本程序的代码比较多,总共有700多行,需要分门别类、有规划地放到不同的源文件中,这就是所谓的模块化编程(也即多文件编程)。在模块化编程中,需要在 .c 文件中定义函数,在 .h 中声明函数、变量、自定义类型、结构体、宏等,请大家猛击《C语言多文件编程》一章了解详情。

    2) 文件操作

    我们的程序将学生信息保存到文件中,并根据学号进行排序,这样在查询和定位时就比较方便。那么,问题来了,如何在文件的中间插入、删除、修改数据呢?如何在文件中定位某个学生的信息呢?请大家阅读《C语言文件操作》一章学习。常见的文件大都是顺序文件,也就是文件内容是依次存储在硬盘上的。顺序文件检索速度快,但是不利于数据的插入、删除和修改。例如,在文件中间插入数据时,理论上要将后面的数据整体后移,但是这会带来风险,很有可能覆盖后面的数据,导致其他文件出错,所以这种方式是绝对禁止的。大家在阅读教程时尤其要注意对顺序文件的插入、删除、修改操作是如何实现的,这是程序得以实现的关键。

    3) 循环菜单

    程序运行时,会不停地显示主菜单和子菜单,而不是执行完一次操作就退出,这是如何实现的呢?请大家猛击《C语言循环菜单的设计,让程序一直运行》了解详情。

    三. 程序的整体架构

    程序由6个文件构成,其中包括3个头文件(.h)和3个源文件(.c)。1) main.c 是主文件,包含了主函数 main() 以及两个打印菜单的函数 printMainMenu()、printSubMain()。2) common.h 是程序的配置文件,每个文件都应该将它包含进去。配置文件中主要是宏定义,每一个宏都是一个配置选项,用户可以更改。例如:

    • FILENAME 宏定义了数据文件的路径,也就是将学生信息保存到何处,默认是当前目录下的 stu.data。如果你希望将文件放在其他目录下,完全可以改成诸如D:\\Demo\stu.dataC:\\data.stu的形式。

    • MAX_STU_AGE 宏定义了学生的最大年龄,如果用户输入的年龄大于该值,就会给出提示。

    3) tools.c 和 tools.h 主要提供了工具类函数。所谓工具类函数,也就是通用函数,它们不针对具体程序编写,可以用在当前程序中,也可以用在其他程序中,在移植的过程中一般不需要修改代码。4) stu.c 和 stu.h 是主要的两个文件,包含了对学生信息进行增删改查的函数。

    四. 索引的建立

    为了方便检索,我们将学生信息按照学号从小到大依次保存到文件中。但即便这样,直接检索文件数据也是非常低效的,所以我们将所有学生的学号保存到一个 int 数组中,这样:1) 新增学生信息时,如果学号和数组中某个元素的值相等,就说明该学生存在,不能插入。2) 新增、删除、修改、查询学生信息时,可以很容易地获取当前学号在数组中的下标,进而计算出该学生信息在文件中的位置。例如,学号10在数组中的下标为5,现在想删除该学生信息,那么将文件内部的位置指针调整到 5*sizeof(STU) 处就可以(STU是保存学生信息的结构体)。这个数组和文件中学生信息的位置直接关联,我们不妨将它称为索引。需要注意的是,每次插入、删除学生信息时都要更新索引,这就是 updateIndex() 函数的作用。总结起来,索引的作用是更高效地检索和定位学生信息。

    12c40ef4b693d11692f5781da45c0b81.png

    展开全文
  • 这是第一次写博客,想着用博客来记录下自己码代码历程,如果有什么不好地方欢迎各位...学生管理系统 问题描述: 简单来说就是,使用C语言对一些特定数据(学生证信息)实现增删改查+统计功能。 整体思路

    这是第一次写的博客,想着用博客来记录下自己码代码的历程,如果有什么不好的地方欢迎各位指正

    从2020.4.2到2020.4.23历时22天,算是把课设的内容完成了,后面还花费了一点时间增加了一点东西,算是给课设的一些加分项吧。加起来大概就是花费了一个月左右的时间完成这个课设。

    因为课设的代码量较大,所以就将代码文件全部放到GitHub上面了,如果有需要的话可以戳这里

    以下是正文内容。


    学生证管理系统

    问题描述:
    简单来说就是,使用C语言对一些特定的数据(学生证信息)实现增删改查+统计的功能。

    整体思路

    在编写代码之前,为了使逻辑思路不那么混乱,所以先使用process画好了大概的流程图,如下:
    在这里插入图片描述接下来为了编写使修改代码的便捷性,选择了之前未曾试过的分开一个个文件编写代码,再用一个头文件将不同文件的代码结合起来。参考了这篇博客,学会了怎么使用自定义头文件。

    数据结构

    在设计的时候考虑到我们的学生号中已经包含了班级等信息,所以为了代码实现的便捷和查找的方便,使用了数组+双链表的数据结构,数据结构的图如下:

    struct CLASS   //定义班级结构体//
    {
        struct STUDENT *tail;   //指向班级最后一个学生//
        struct STUDENT *head;   //指向班级第一个学生//
        int num;                //存储班级人数//
    };
    
    struct STUDENT                  //定义学生数据结构体//
    {
        struct STUDENT *last;   //指向下一个学生指针//
        char name[20];          //学生姓名//
        char sex[10];           //学生性别//
        char faculty[50];       //学生学院//
        char major[50];         //学生专业//
        char identity[20];      //学生身份//
        char ID[20];            //学生学号//
        char card_number[20];   //学生证卡号///
        char expiration_date[20];//学生证有效日期//
        struct STUDENT *next;     //指向下一个学生指针//
    
    };
    

    文件操作

    • 因为个人觉得在一个程序中不断打开和关闭文件可能会有点麻烦,在代码实现上好像也不怎么方便(主要是因为懒。。。)
      所以只在打开和关闭程序的时候分别进行一次文件读取。当然如果数据量过大的话这种方法还是不可行的。

    相关代码文件:getin.c,close_down.c,start_up.c

    页面设计

    整体的页面采用了上半部分为程序的主要内容,下面留下了3行的空间作为输入指令和提示的空间使用函数print_head()打印整个程序的框架。

    //****************************************************************//
    //调用此函数,则可以清空屏幕,并打印出程序边框,最后光标在(24,9)//
    //****************************************************************//
    
    
    //边框四角: (24,6),(86,6),(24,28),(86,28)//
    //上下中点纵坐标标:18//
    //左右中点横坐标:55//
    
    #include"function.h"
    
    void print_head()
    {
        int i;
        system("cls");
        gotoxy(24,6);
        for(i=0; i<16; i++)  //设置上边框//
        {
            printf("——");
        }
        gotoxy(47,7);
        printf("|学生证管理程序|\n");         //程序名字//
        gotoxy(47,8);
        printf("————————\n");                 //程序名字下划线//
    
        gotoxy(24,28);
        for(i=0; i<16; i++)  //设置下边框//
        {
            printf("——");
        }
    
        for(i=6; i<=28; i++)    //设置左右边框//
        {
            gotoxy(23,i);
            printf("|");
            gotoxy(86,i);
            printf("|");
        }
    
        gotoxy(24,24);          //设置提示栏//
        for(i=24; i<=84; i++)
        {
            printf("-");
        }
        gotoxy(24,9);           //跳转光标//
    }
    
    

    菜单

    在这里插入图述

    基本功能

    基本功能的实现都是比较基本的内容,没有太多可讲道的地方,可以选择直接跳过

    添加学生证信息

    相关代码文件:enter.c,getin.c

    主要的思路:将信息依次录入到一个临时变量中,在输入完之后用户再输入确定的指令,然后将临时变量传入到输入数据到存储的结构体中的函数中,完成输入。

    删除学生证信息

    相关代码文件:del.c,ask_id.c

    主要思路:先询问用户需要删除的学号,在用户输入正确的学号之后将该学号的信息打印出来,询问用户是否为该学号,之后用户选择确定之后成功删除。

    按班级查询

    相关代码文件:相关代码:show_class

    主要思路:询问班级号,再将班级中的学生信息打印出来,由于使用了双向链表的结构来连接学生的信息,所以用户可以通过按‘←’和‘→’,来浏览学生的信息。

    这部分代码感觉挺有意思的,贴在下面。

        if(clarr[n].head==NULL)             //若该班级头指针为空//
        {
            print_head();
            gotoxy(42,12);
            printf("|显示失败,并没有学生在%d班|",n);
            clean_tip();
            return go_back();               //询问用户下一步操作//
        }
        else
        {
            p1=clarr[n].head;               //p1指向班级首名学生//
    
            while(1)
            {
                print_student(*p1);             //打印学生信息//
                gotoxy(24,25);
                printf("显示成功,%d班信息如上,按←和→进行浏览。",n);  //提示栏语句//
                err=getset();
                gotoxy(24,26);
                printf("按0退出程序,1返回主菜单。");
                while(1)
                {
                    key_down=getch();               //键盘输入,使程序继续显示下一名学生//
                    if(key_down==-32)               //用于消除getch读取方向键时第一次返回的值,该死,不不知道为什么是-32//
                    {
                        continue;
                    }
                    if(key_down==75)
                    {
                        if(p1->last!=NULL)
                        {
                            p1=p1->last;
                            clean_tip();                            //清除提示栏//
                            break;
                        }
                        else
                        {
                            gotoxy(24,27);
                            printf("已是第一位学生");
                        }
                    }
                    else if(key_down==77)
                    {
                        if(p1->next!=NULL)
                        {
                            p1=p1->next;
                            clean_tip();                            //清除提示栏//
                            break;
                        }
                        else
                        {
                            gotoxy(24,27);
                            printf("已是最后一位学生");
                        }
                    }
                    else if(key_down=='0')
                    {
                        return 0;
                    }
                    else if(key_down=='1')
                    {
                        return 1;
                    }
                    else
                    {
                        error(err);
                    }
                }
            }
        }
    

    按学号查询

    相关代码文件:show_student.c,print_student.c

    主要思路:询问用户学号,若存在学号则直接打印学生信息,否则用户可以选择返回主菜单重新查询。

    修改学生信息

    相关代码文件:modify.c,modify_op.c

    主要思路:询问学号→打印信息→选择修改项→输入修改内容→打印修改后信息→选择返回或继续修改。

    统计功能

    相关代码文件:statistics.c,sta_*,print_sex_table,

    这部分功能可以选择统计班级人数,总人数,班级性别比例,总性别比例四项。

    主要思路:
    班级人数在班级结构体中已经进行了存储,所以统计时直接输出就可以
    总人数就是对班级人数遍历一遍然后进行统计。
    性别比例则是通过对班级中的学生性别进行一遍遍历然后进行统计。由于输入的不确定,所以将性别设置为了3个种类:男(boy),女(girl),其他

    有用的辅助函数

    这部分包括用来处理程序中一些可能出现的细节问题,以及为了方便程序设计而使用的一些函数。

    定位函数

    相关代码文件:gotoxy.c、getset.c

    gotoxy(int x,int y):这个函数可以使当前光标移动到坐标(x,y)上
    POINT getset():这个函数通过返回POINT的值获得当前光标的位置。
    两个函数组合起来就可以很方便的对整个程序的框架进行设计。

    参考博文:戳这里

    输入函数

    相关代码文件:super_scan、super_int_scan

    • 由于在输入的时候考虑到用户可能会有许多非法输入,比如什么都不输入直接按回车这种情况导致光标会跳出输入框,所以设计了两个输入函数用来处理用户的非法输入。

    在这里插入图片描述
    可以看到如果直接使用scanf输入姓名字符串时,如果用户不输入字符,
    直接点击回车,光标此时会跳出程序外面,造成‘穿模’,但是在使用了输入函数之后:
    在这里插入图片描述
    如果直接输入回车,则会在提示栏中提示“输入不能为空”。

    代码如下:
    第一个用来输入字符以及字符串都可以。

    //可以检测输入是否为空,并且没有多余的回车,将输入的整型存在上个函数传递进来的地址中//
    
    #include "function.h"
    
    int super_scan(char temp[])
    {
        char t;
        int i=0;
        POINT p;
        p=getset();
        while(1)
        {
            if((t=getchar())==EOF)
            {
                return 0;
            }
            if(t=='\n'&&i==0)
            {
                gotoxy(24,26);
                printf("输入不能为空");
                gotoxy(p.x,p.y);
            }
            else if(t=='\n')
            {
               break;
            }
            else
            {
                temp[i++]=t;
            }
        }
        return 1;
    }
    

    第二个用来输入整型

    //可以检测输入是否为空,并且没有多余的回车,将输入的整型存在上个函数传递进来的地址中//
    
    #include "function.h"
    
    int super_int_scan(int *n)
    {
        char t;
        int i=1;
        char a[50]={0};
        POINT p;
        a[0]='*';
        p=getset();
        while(1)
        {
    
            if((t=getchar())==EOF)
            {
                return 0;
            }
            if(t=='\n'&&i==1)
            {
                gotoxy(24,26);
                gotoxy(p.x,p.y);
            }
            else if(t=='\n')
            {
               break;
            }
            else
            {
                a[i++]=t;
            }
        }
        *n=transf(a);
        return 1;
    }
    

    返回函数

    相关代码文件:go_back.c

    • 由于在完成不同的基本功能之后都有返回主菜单的需求,所以将其包装起来,在使用的时候直接调用。

    错误处理函数:

    相关代码文件:error.c

    • 对于用户的非法输入,我的处理方法是将用户的输入清除,然后对用户进行提醒,让其重新输入。此函数可以实现这一功能。
    //该函数用于处理非法输入情况//
    
    #include"function.h"
    
    #pragma comment(lib,"Winmmlib")
    void error(POINT point)
    {
    
        PlaySound(TEXT("err.wav"),NULL,SND_FILENAME | SND_ASYNC);
    
    
        gotoxy(49,27);
        printf("输入错误,请重试");         //提示栏提示//
        gotoxy(point.x,point.y);
        printf("             ");               //消除上次输入内容//
        gotoxy(point.x,point.y);
    
    }
    

    操作成功函数

    相关代码文件:success.c

    • 对于某些操作做,如录入,删除,用户在操作之后可能感觉不到自己以及成功了,会有点不确定的感觉,此时额外加入一个界面告知用户操作已经成功,提示用户的操作体验。
    int success()
    {
        print_head();
        gotoxy(50,15);
        printf("—————");
        gotoxy(50,16);
        printf("|操作成功!|");
        gotoxy(50,17);
        printf("—————");
    
        return go_back();
    }
    

    数据类型转换函数

    • 在录入文本信息已经用户输入学号时,由于需要从学号中提取出班级编号进行‘分班’处理,所以使用了一个数据类型转换的函数进行处理。
    • 这函数有三个功能,1、从学号中提取出班级编号;2、将文本中的班级人数转换为整型;3、将文本中班级编号转换为整型。
    //调用此函数从学号中提取班级整形编码//
    //调用此函数也可将文件中班级编码字符串转换为整型//
    //调用此函数还可以提取班级总人数//
    
    #include"function.h"
    #include <math.h>
    
    int transf(char *a)
    {
        int i,sum=0,len,j,mul;
        if(a[0]=='*')                       //判断为班级编号标识符//
        {
            len=strlen(a);
            for(i=1;i<len;i++)          //将字符串转换为整型并返回//
            {
                for(j=len-i,mul=1;j>1;j--)
                {
                    mul*=10;
                }
                sum+=(a[i]-48)*mul;
            }
        }
        else if(a[0]=='&')              //判断为班级人数标识符//
        {
            len=strlen(a);
            for(i=1;i<len;i++)          //将字符串转换为整型并返回//
            {
                for(j=len-i,mul=1;j>1;j--)
                {
                    mul*=10;
                }
                sum+=(a[i]-48)*mul;
            }
        }
        else                            //判读为学号//
        {
            for(i=7;i<10;i++)           //对学号的去间进行转换//
            {
                if(i==7)
                {
                    sum+=(a[i]-48)*100;
                }
                else if(i==8)
                {
                    sum+=(a[i]-48)*10;
                }
                else if(i==9)
                {
                    sum+=(a[i]-48)*1;
                }
            }
        }
        if(sum>0&&sum<10000)            //班级编码只在1~9999之间,所以只返回这个区间的值//
        {
            return sum;
        }
        else                            //其他的则返回0//
        {
            return 0;
        }
    
    
    }
    

    有趣的额外功能

    添加音效

    • 由于觉得这个程序做完之后还是太过单调,没有什么有趣的地方,用户使用起来可能会觉得很无聊,所以在一些操作上加入了按键的音效,比如删除成功的音效,菜单选择的音效,进出程序,退出程序等音效。为了使用户更有熟悉感,这些音效据采用了Windows的内置系统音效。

    添加音效主要使用PlaySound语句。

     PlaySound(TEXT("welcome.wav"),NULL,SND_FILENAME | SND_ASYNC );
    

    详情使用方法参考这里

    添加加载和退出页面

    相关代码文件:welcom.c、outsys.c

    • 原本是为了在答辩时用一些一些特别的东西吸引一下老师的注意力,让答辩了一天的老师感到不那么疲惫。所以添加了一些有趣的加载和退出界面。但是因为疫情,又不用答辩了。。。。。。

    实现效果:
    在这里插入图片描述
    底部的方块是加载条,以90ms一格的速度加载,配合着打开的音效刚好在音效播放完时加载完毕。
    在这里插入图片描述

    退出界面小人的手会以200ms/帧的速率进行摆动。

    实现方法:主要用到了循环和sleep()函数,控制程序运行的速度,这样就能形成加载和运动的感觉。

    以下是加载界面代码:

    #include "function.h"
    #pragma comment(lib,"Winmmlib")
    void welcome()
    {
        int x,y,i;
    
        PlaySound(TEXT("welcome.wav"),NULL,SND_FILENAME | SND_ASYNC );
        print_head();
        x=46;
        y=8;
        gotoxy(x,++y);
        printf("  ■■■■■■■  ");gotoxy(x,++y);
        printf(" ■            ■  ");gotoxy(x,++y);
        printf("■              ■ ");gotoxy(x,++y);
        printf("■  ■     ■   ■ ");gotoxy(x,++y);
        printf("■ ■■   ■■  ■ ");gotoxy(x,++y);
        printf("■              ■ ");gotoxy(x,++y);
        printf("■   ■    ■   ■         ");gotoxy(x,++y);
        printf(" ■   ■■■   ■   ■■    ");gotoxy(x,++y);
        printf("  ■          ■   ■##■   ");gotoxy(x,++y);
        printf("   ■■■■■■     ■■     ");gotoxy(x,++y);
        printf("      ■■■       ■      ");gotoxy(x,++y);
        printf("■■■■■■■■■■       ");gotoxy(x,++y);
        printf("      ■■■       ");gotoxy(x,++y);
        printf("  欢迎使用本程序  ");
    
    
    
    
        gotoxy(24,25);
        printf("加载中");
    
    
        gotoxy(24,27);
        for(i=24;i<55;i++)
        {
            printf("■");
            Sleep(90);
        }
        gotoxy(24,25);
        printf("加载完毕,按任意建进入程序");
    
    
        getch();
        gotoxy(30,30);
    
    }
    

    以下是退出动画代码:

    #include"function.h"
    #pragma comment(lib,"Winmmlib")
    
    void outsys()
    {
        PlaySound(TEXT("close.wav"),NULL,SND_FILENAME | SND_ASYNC );
        int x,y,i;
        print_head();
        x=46;
        y=8;
        gotoxy(x,++y);
        printf("  ■■■■■■■  ");gotoxy(x,++y);Sleep(80);
        printf(" ■            ■  ");gotoxy(x,++y);Sleep(80);
        printf("■              ■ ");gotoxy(x,++y);Sleep(80);
        printf("■  ■     ■   ■ ");gotoxy(x,++y);Sleep(80);
        printf("■ ■■   ■■  ■ ");gotoxy(x,++y);Sleep(80);
        printf("■              ■ ");gotoxy(x,++y);Sleep(80);
        printf("■   ■    ■   ■ ");gotoxy(x,++y);Sleep(80);
        printf(" ■   ■■■   ■  ");gotoxy(x,++y);Sleep(80);
        printf("  ■          ■   ");gotoxy(x,++y);Sleep(80);
        printf("   ■■■■■■    ");gotoxy(x,++y);Sleep(80);
        printf("      ■■■       ");gotoxy(x,++y);Sleep(80);
        printf("■■■■■■■■■ ");gotoxy(x,++y);Sleep(80);
        printf("      ■■■       ");gotoxy(x,++y);Sleep(80);
        printf("  感谢使用本程序  ");
    
    
        gotoxy(24,25);
        printf("已成功退出,按任意键继续");
    
    
    
    i=1;
    while(!_kbhit())
    {
    
        i++;
        x=64;y=15;
        gotoxy(x,++y);
        printf("  ■■");gotoxy(x,++y);
        printf(" ■##■");gotoxy(x,++y);
        printf("  ■■");gotoxy(x,++y);
        printf(" ■");gotoxy(x,++y);
        printf("■");gotoxy(x,++y);
        Sleep(200);
        x=64;y=15;
        gotoxy(x,++y);
        printf("      ");gotoxy(x,++y);
        printf("       ");gotoxy(x,++y);
        printf("     ");gotoxy(x,++y);
        printf("   ");gotoxy(x,++y);
        printf("  ");gotoxy(x,++y);
    
        x=64;y=17;
        gotoxy(x,++y);
        printf("     ■■");gotoxy(x,++y);
        printf("■■■##■");gotoxy(x,++y);
        printf("     ■■");gotoxy(x,++y);
        Sleep(200);
    
         x=64;y=17;
        gotoxy(x,++y);
        printf("         ");gotoxy(x,++y);
        printf("          ");gotoxy(x,++y);
        printf("         ");gotoxy(x,++y);
    
        if(i==100)
        {
            break;
        }
    }
    
    
        x=64;y=17;
        gotoxy(x,++y);
        printf("     ■■");gotoxy(x,++y);
        printf("■■■##■");gotoxy(x,++y);
        printf("     ■■");gotoxy(x,++y);
        getch();
        gotoxy(30,30);
    
    }
    



    本次课设的思路和代码基本介绍完成,如果有任何修改意见或问题欢迎各位提出。

    这也是本人第一次第一次写博客,以后会继续更新的,撒花花❀❀

    展开全文
  • C语言实现学生成绩管理系统(小白也看得懂)

    千次阅读 多人点赞 2020-01-31 11:03:09
    C语言实现学生成绩管理系统(小白也看得懂) ...程序设计的整体思路 程序主要实现思路是依靠链表,数组,指针,结构体等相关知识,其中的核心是对链表的操作。 ①:使用单链表作为程序核心,单链表...

    程序需要实现的功能

    C语言学生信息管理系统包括以下几个功能:
    1、学生成绩的录入
    2、学生成绩的浏览
    3、学生成绩的查询
    4、学生成绩的删除
    5、学生成绩的排序(这是进阶功能,实现起来也最复杂)
    6、学生成绩的分析

    程序设计的整体思路

    程序主要实现思路是依靠链表,数组,指针,结构体等相关知识,其中的核心是对链表的操作。
    ①:使用单链表作为程序核心,单链表的每个结点储存一个学生的基本信息
    ②:创建一个函数类 ;主要包含以下功能的函数:创建链表,创建结点,插入结点,打印链表,删除结点等
    ③:创建一个功能类;主要包含主菜单功能显示以实现用户自主选择功能,操作函数

    源代码

    主函数(main)

    为了使代码看起来更为简洁明了,我将实现链表功能的函数类放入student.h的头文件中,主函数中只留有main函数
    首先需要完成对功能菜单栏的设计,为此,我创建了一个menu函数,为了使界面看起来更美观,可以加入一些符号

    menu

    void menu(void)
    {
    	printf("\t\t||--------------------------------------------------------------------------------||\n");
    	printf("\t\t||                 ****************【学生管理系统】***************                ||\n");
    	printf("\t\t||--------------------------------------------------------------------------------||\n");
    	printf("\t\t||*                                 1.学生成绩录入                                ||\n");
    	printf("\t\t||*                                 2.学生成绩浏览                                ||\n");
    	printf("\t\t||*                                 3.学生成绩查询                                ||\n");
    	printf("\t\t||*                                 4.学生成绩删除                                ||\n");
    	printf("\t\t||*                                 5.学生成绩排序                               ||\n");
    	printf("\t\t||*                                 6.学生成绩分析                                ||\n");
    	printf("\t\t||*                                 0.退出程序                                    ||\n");
    	printf("\t\t||--------------------------------------------------------------------------------||\n");
    }
    

    main函数的构建则依赖于while的无限循环,用来让用户不断选择功能直到其按0退出
    while循环内再嵌套一个switch函数来判断用户输入的数字以跳转到相应的功能

    main

    int main(void)
    {
    	menu();
    	
    	while (1)
    	{
    		int choice;
    		printf("请选择功能菜单(0-6): ");
    		scanf("%d", &choice);
    		
    		switch (choice)
    		{
    			case 1:
    			{
    				printf("-----------------【学生成绩录入】----------------------\n");
    				break;
    			}
    			case 2:
    			{
    				printf("-----------------【学生成绩浏览】----------------------\n");
    				break;
    			}
    			case 3:
    			{
    				printf("-----------------【学生成绩查询】----------------------\n");
    				break;
    			}
    			case 4:
    			{
    				printf("-----------------【学生成绩删除】----------------------\n");
    				break;
    			}
    			case 5:
    			{
    				printf("-----------------【学生成绩排序】----------------------\n");
    				break;
    			}
    			case 6:
    			{
    				printf("-----------------【学生成绩分析】----------------------\n");
    				printf("该系统提供学生成绩方差来帮助分析学生成绩\n");
    				break;
    			}
    			default:
    			{
    				printf("谢谢使用^_^!\n");
    				system("pause");
    				exit(0);
    				break;
    			}
    			
    		}
    
    
    	}
    	return 0;
    }
    

    以上就是主函数的整体框架,接下来要做的就是编写函数类,再往主函数里填充。

    头文件( student.h)

    头文件里主要包含函数类

    创建链表:

    创建学生信息结构体:

    首先我们需要完成对链表的构建,为此我们先创建一个学生信息结构体来表示一个学生的姓名学号语文、英语、数学、物理四颗成绩

    struct grade     
    {
    	int Chinese;
    	int English;
    	int Math;
    	int physical;
    };
    
    struct student   //学生信息结构体
    {
    	char name[20];
    	int number;
    	struct grade grade;
    };
    

    接下来就是编写链表的有关函数了

    Creatlist(创建链表)

    struct Node   //单个链表结点
    {
    	struct student data;
    	struct student* next;
    };
    
    struct Node* Creatlist(void)     //创建链表
    {
    	struct Node* HeadNode = (struct Node*)malloc(sizeof(struct Node));   //创建一个头结点,头结点表示此链表
    	HeadNode->next = NULL;
    	return HeadNode;
    }
    

    CreatNode(创建结点)

    struct Node* CreatNode(struct student data)  //创建结点
    {
    	struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
    	NewNode->data = data;     //数据域
    	NewNode->next = NULL;     //指针域
    	return NewNode;
    }
    

    InsertNode(插入结点)

    链表结点的插入方法有很多种,像头插法,尾插法等,为了简便,这里采用头插法

    void InsertNode(struct Node* HeadNode, struct student data)
    {
    	struct Node* NewNode = CreatNode(data);  //创建一个新结点来插入
    	NewNode->next = HeadNode->next;  //该结点的指针域指向头结点的下一个结点
    	HeadNode->next = NewNode;   //头结点的指针域指向该结点
    	return;
    }
    

    deleteNode(删除结点)

    可以依据多种根据来删除结点,这里我们指定学号来删除结点

    void deleteNode(struct Node* HeadNode, int num)  //删除结点(根据指定学号删除)
    {
    	struct Node* postNode = HeadNode->next;
    	struct Node* postNodebefore = HeadNode;
    	if (postNode == Null)
    		printf("系统暂无任何学生信息,无法进行删除\n");
    	else
    		while (postNode->data.number != num)
    		{
    			postNodebefore = postNode;
    			postNode = postNode->next;
    			if (postNode == Null)
    			{
    				printf("系统中无该学生信息,无法进行删除\n");
    				return;
    			}
    		}
    	postNodebefore->next = postNode->next;
    	free(postNode);
    }
    

    printList(打印链表)

    void printList(struct Node* HeadNode) //打印链表
    {
    	struct Node* pMove;
    	pMove = HeadNode->next;
    
    	if (pMove == NULL)
    		printf("无学生信息\n");
    	else
    	{
    		printf("学号\t姓名\t语文\t英语\t数学\t物理\n");
    		while (pMove != NULL)
    		{
    			printf("%d %s %d %d %d %d", pMove->data.number, pMove->data.name, pMove->data.grade.Chinese, pMove->data.grade.English, pMove->data.grade.Math, pMove->data.grade.physical);
    			pMove = pMove->next;
    		}
    		printf("\n");
    	}
    

    seachNode(查询结点)

    void searchNode(struct Node* HeadNode, int number)  //根据学生学号来查询学生成绩
    {
    	struct Node* pMove = HeadNode->next;
    	if (pMove == NULL)
    		printf("无学生信息\n");
    	else
    	{
    		while (pMove != NULL)
    		{
    			if (number == pMove->data.number)
    			{
    				printf("学号\t姓名\t语文\t英语\t数学\t物理\n");
    				printf("%d %s %d %d %d %d", pMove->data.number, pMove->data.name, pMove->data.grade.Chinese, pMove->data.grade.English, pMove->data.grade.Math, pMove->data.grade.physical);
    				break;
    			}
    			pMove = pMove->next;
    		}
    		printf("\n");
    	}
    }
    

    由此,链表类函数已经全部构建完毕,函数的作用使一个个功能独立封装,在调用时直接引用函数即可,可是程序变得简单易读,也是写程序变得更有条理。

    接下来,就是与主函数的整合了

    整体整合

    主函数

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include"student.h"
    
    
    //主函数
    int main (void)
    {
    	menu();//打印界面
    
    	//声明变量
    	struct student newstudent;
    	int choice , month;
    	struct Node*List=Creatlist();
    
    	while (1) 
    	{
    		printf("请选择功能菜单(0-6):");
    		scanf("%d", &choice);
    	
    		switch (choice) 
    		{
    			case 1:
    			{
    				printf("-----------------【学生成绩录入】----------------------\n");
    				printf("请输入学生的学号和姓名:\n");
    				fflush(stdin);//字符串输入之前清空缓冲区
    				scanf("%d%s", &newstudent.number, newstudent.name);
    
    				printf("请输入学生的成绩(语文/英语/数学/物理):");
    				scanf("%d%d%d%d", &newstudent.grade.Chinese, &newstudent.grade.English, &newstudent.grade.Math, &newstudent.grade.physical);
    				
    				InsertNode(List, newstudent);  //数据存入结点中
    
    			}break;
    			
    			case 2:
    			{
    				printf("-----------------【学生成绩浏览】----------------------\n");
    
    				printList(List);
    
    			}break;
    		
    			case 3:
    			{
    				printf("-----------------【学生成绩查询】----------------------\n");
    			
    				int search_number;
    				printf("请输入您想要查询的学号:");
    				scanf("%d", &search_number);
    
    				searchNode(List, search_number);//根据学号打印出学生成绩
    			
    			}break;
    		
    			case 4:
    			{
    				system("CLS");
    				printf("-----------------【学生成绩删除】----------------------\n");
    				int delete_number;
    
    				printf("请输入要删除学生的学号:");
    				scanf("%d", &delete_number);
    
    				deleteNode(List,delete_number);//根据学生学号删除
    
    				printf("%d号学生已删除\n",delete_number);
    
    			}break;
    		
    			case 5:
    			{
    				system("CLS");
    				printf("-----------------【学生成绩排序】----------------------\n");
    			}break;
    
    			
    			case 0:
    			{
    				system("CLS");
    				printf("谢谢使用^_^!\n");
    				system("pause");
    				exit(0);
    
    			}break;
    		
    			default:
    			{
    				system("CLS");
    				printf("选择错误,请重新输入0.0\n");
    			}break;
    		}
    	}
    
    	system("pause");
    	return 0;
    }
    

    头文件 <student.h>:

    #include<stdio.h>
    #include<stdlib.h>
    
    //功能菜单
    void menu(void)
    {
    	printf("\t\t||--------------------------------------------------------------------------------||\n");
    	printf("\t\t||                 ****************【学生管理系统】***************                ||\n");
    	printf("\t\t||--------------------------------------------------------------------------------||\n");
    	printf("\t\t||*                                 1.学生成绩录入                                ||\n");
    	printf("\t\t||*                                 2.学生成绩浏览                                ||\n");
    	printf("\t\t||*                                 3.学生成绩查询                                ||\n");
    	printf("\t\t||*                                 4.学生成绩删除                                ||\n");
    	printf("\t\t||*                                 5.学生成绩排序                               ||\n");
    	printf("\t\t||*                                 0.退出程序                                    ||\n");
    	printf("\t\t||--------------------------------------------------------------------------------||\n");
    }
    
    struct grade
    {
    	int Chinese;
    	int English;
    	int Math;
    	int physical;
    };
    
    struct student   //学生信息结构体
    {
    	char name[20];
    	int number;
    	struct grade grade;
    };
    
    struct Node   //单个链表结点
    {
    	struct student data;
    	struct student* next;
    };
    
    struct Node* Creatlist(void)     //创建链表
    {
    	struct Node* HeadNode = (struct Node*)malloc(sizeof(struct Node));   //创建一个头结点,头结点表示此链表
    	HeadNode->next = NULL;
    	return HeadNode;
    }
    
    struct Node* CreatNode(struct student data)  //创建结点
    {
    	struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
    	NewNode->data = data;     //数据域
    	NewNode->next = NULL;     //指针域
    	return NewNode;
    }
    
    void InsertNode(struct Node* HeadNode, struct student data)
    {
    	struct Node* NewNode = CreatNode(data);  //创建一个新结点来插入
    	NewNode->next = HeadNode->next;  //该结点的指针域指向头结点的下一个结点
    	HeadNode->next = NewNode;   //头结点的指针域指向该结点
    	return;
    }
    
    void deleteNode(struct Node* HeadNode, int num)  //删除结点(根据指定学号删除)
    {
    	struct Node* postNode = HeadNode->next;
    	struct Node* postNodebefore = HeadNode;
    	if (postNode == Null)
    		printf("系统暂无任何学生信息,无法进行删除\n");
    	else
    		while (postNode->data.number != num)
    		{
    			postNodebefore = postNode;
    			postNode = postNode->next;
    			if (postNode == Null)
    			{
    				printf("系统中无该学生信息,无法进行删除\n");
    				return;
    			}
    		}
    	postNodebefore->next = postNode->next;
    	free(postNode);
    }
    
    void printList(struct Node* HeadNode) //打印链表
    {
    	struct Node* pMove;
    	pMove = HeadNode->next;
    
    	if (pMove == NULL)
    		printf("无学生信息\n");
    	else
    	{
    		printf("学号\t姓名\t语文\t英语\t数学\t物理\n");
    		while (pMove != NULL)
    		{
    			printf("%d %s %d %d %d %d", pMove->data.number, pMove->data.name, pMove->data.grade.Chinese, pMove->data.grade.English, pMove->data.grade.Math, pMove->data.grade.physical);
    			pMove = pMove->next;
    		}
    		printf("\n");
    	}
    }
    
    void searchNode(struct Node* HeadNode, int number)  //根据学生学号来查询学生成绩
    {
    	struct Node* pMove = HeadNode->next;
    	if (pMove == NULL)
    		printf("无学生信息\n");
    	else
    	{
    		while (pMove != NULL)
    		{
    			if (number == pMove->data.number)
    			{
    				printf("学号\t姓名\t语文\t英语\t数学\t物理\n");
    				printf("%d %s %d %d %d %d", pMove->data.number, pMove->data.name, pMove->data.grade.Chinese, pMove->data.grade.English, pMove->data.grade.Math, pMove->data.grade.physical);
    				break;
    			}
    			pMove = pMove->next;
    		}
    		printf("\n");
    	}
    }
    

    !!!注:排序函数的构建由于所学有限,可以将录入的学生成绩储存在一个数组中,对数组中元素进行排序是很简单的

    总结

    项目的构建最先需要设想好程序应当实现的功能在进行编写,把需要多次调用的功能用函数封装起来,使程序更简单,主函数和头文件的分类也更方便他人阅读。

    成绩管理系统使较为简单的一个项目,比较适合大一新生上手锻炼实践,需要对链表,指针有足够的熟悉。

    展开全文
  • 一 项目整体概述 本次老师让我们做一个以数据库为基础...因此,我们把它放到了一个现实系统当中,这样可以更加生动形象理解登陆界面和数据库综合应用技术,所以,我们做出了学生信息管理系统! 二 设计思路...
  • 通过学习学生信息管理系统软件,我了解到了基于函数结构化大型程序编写方法;了解到C语言管理软件的设计方法和编程思路。大概知道了编写流程、要点还有一些基本命令。 首先,要明确编写题目,也就是编写...
  • 在做一个资产管理系统,碰到资产盘点的设计和实现。整体是工作流。本人是大三学生,一直都处在很菜程度上。第一次接触项目,碰到这个地方居然晕了。汗一个,流图已经有了,自己看半天看晕了。晚上回来找找网上...
  • c++课程设计图书馆管理系统总结

    千次阅读 2018-07-07 16:17:29
    从刚开始做图书馆管理系统到现在,经过了无数次修改,由程序不成熟逐步发展,更新,整个过程中,我得到了很多收获,下面简单说一下自己感悟:做任何一个程序,一开始必须要有一个总规划,整体的思路必须在...
  • 系统可以作为计算机专业学生的大作业,也可以作为毕业设计,代码中注释占有很高,方便参考者学习,对学习框架,整体的思路有很大帮助
  • 嵌入式系统原理与设计.pdf

    千次下载 热门讨论 2012-12-05 22:27:22
    《嵌入式系统原理与设计》适合计算机、软件工程、电子、电气、机电一体化、光电等相关专业研究生或本科高年级学生选作教材,同时也可作为从事嵌入式系统项目管理整体设计和硬件、软件开发技术人员参考书。
  • 试卷生成模块是整个题库管理系统的核心。本系统的组卷是采用交互方式,即用户在输入各种要求后,系统会自动生成一份符合要求的试卷。组卷过程中系统会向用户依次询问以下信息: (1) 要生成的试卷满分分数 (2) ...
  • 首先是操作系统的名字改变了,原因在于虽然我们的试验性 OS从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix(本意为 TryMinix)改成了新名字...
  • 首先是操作系统的名字改变了,原因在于虽然我们的试验性 OS从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix(本意为 TryMinix)改成了新名字...
  • 面向对象方法中的对象,是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位,由一组属性和一组行为构成。 面向对象的方法将数据及对数据的操作方法放在一起,作为一个相互依存、不可分离的整体--...
  • c++软件开发心得

    2019-06-22 16:18:11
    和上一个学期相比是完全不同的体验,开始进行了软件设计开发,在老师的引领下,尝试了几个简单的软件设计,有学生成绩管理系统、ATM机系统、通讯录还有最后的图书管理系统,在研究学习这几个系统的过程中,有了很多...
  • ASP.NET精品课程+源代码

    千次下载 热门讨论 2009-01-05 20:15:51
    ASP.NET精品课程整体设计 一、 概述 《ASP.NET程序设计》课程是一门重要计算机专业课,它是计算机网络、计算机软件及应用、计算机技术及应用、计算机信息管理、计算机网络管理及维护、电子商务、计算机多媒体技术...
  • 本书在介绍C++特性的同时,讨论了基本C语言,使二者成为有机的整体。书中介绍了C++的基本概念, 并通过短小精悍的程序来阐明,这些程序都很容易复制和试验。还介绍了输入和输出、如何让程序执行重 复性任务、如何...
  • 本书在介绍C++特性的同时,讨论了基本C语言,使二者成为有机的整体。书中介绍了C++的基本概念, 并通过短小精悍的程序来阐明,这些程序都很容易复制和试验。还介绍了输入和输出、如何让程序执行重 复性任务、如何...
  • 本书在介绍C++特性的同时,讨论了基本C语言,使二者成为有机的整体。书中介绍了C++的基本概念, 并通过短小精悍的程序来阐明,这些程序都很容易复制和试验。还介绍了输入和输出、如何让程序执行重 复性任务、如何...
  • C#数据结构

    2013-12-10 11:49:54
    数据元素是数据基本单位,在计算机程序中通常被作为一个整体进行考虑 和处理。数据元素有时也被称为元素、结点、顶点、记录等。一个数据元素可由 若干个数据项(Data Item)组成。数据项是不可分割、含有独立意义...
  • C++网络爬虫项目

    2018-07-04 00:59:17
    “DNS解析”也处理为并发的过程,以避免爬虫系统的I/O吞吐率受到网站服 务器和域名解析服务器的限制。而对于“已抓取URL队列”则可以采用布隆排 重表的方式加以优化,以降低其时间和空间复杂度。 2. 总体架构 本项目...
  • C语言编程100例精选源码

    热门讨论 2009-10-29 01:31:44
    实例30 停车场管理系统 91 第3部分 文本屏幕与文件操作篇 实例31 菜单实现 96 实例32 窗口制作 97 实例33 模拟屏幕保护程序 100 实例34 文件读写基本操作 102 实例35 格式化读写文件 105 实例36 成块...
  • c语言编写单片机技巧

    2009-04-19 12:15:17
    答:大学过程是一个理论过程,实践的机会比较少,往往会造成理论与实践相脱节,这是国内大学教育系统的通病,不过对于学生来说切不可好高骛远。一般从大三会开始接触到一些专业课程,电子相关专业会开设相关的...
  • iPhone开发秘籍(第2版)--源代码

    热门讨论 2012-12-11 13:51:22
    3.7 简单内存管理 85 3.7.1 创建对象 85 3.7.2 创建自动释放对象 86 3.7.3 自动释放对象生命周期 87 3.7.4 保留自动释放对象 87 3.7.5 已保留属性 87 3.7.6 高保留计数 89 3.7.7 创建对象其他方式...

空空如也

空空如也

1 2
收藏数 24
精华内容 9
关键字:

学生管理系统的整体设计思路