-
算法c语言源码_C语言学生信息管理系统源码下载和思路解析(密码版)
2021-01-10 02:10:48在《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.data
、C:\\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 对学生信息进行解密,否则提示用户密码错误。
-
c 包含其他文件_C语言学生信息管理系统源码下载和思路解析(文件版)
2020-12-28 16:35:52在《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.data
、C:\\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() 函数的作用。总结起来,索引的作用是更高效地检索和定位学生信息。
-
高级语言程序设计课设-学生证管理系统-华南农业大学
2020-06-10 20:56:08这是第一次写的博客,想着用博客来记录下自己码代码的历程,如果有什么不好的地方欢迎各位...学生证管理系统 问题描述: 简单来说就是,使用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:09C语言实现学生成绩管理系统(小白也看得懂) ...程序设计的整体思路 程序主要实现思路是依靠链表,数组,指针,结构体等相关知识,其中的核心是对链表的操作。 ①:使用单链表作为程序核心,单链表...程序需要实现的功能
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"); } }
!!!注:排序函数的构建由于所学有限,可以将录入的学生成绩储存在一个数组中,对数组中元素进行排序是很简单的
总结
项目的构建最先需要设想好程序应当实现的功能在进行编写,把需要多次调用的功能用函数封装起来,使程序更简单,主函数和头文件的分类也更方便他人阅读。
成绩管理系统使较为简单的一个项目,比较适合大一新生上手锻炼实践,需要对链表,指针有足够的熟悉。
-
梦之翼团队项目(学生信息管理系统)
2015-12-04 20:23:00一 项目整体概述 本次老师让我们做一个以数据库为基础...因此,我们把它放到了一个现实的系统当中,这样可以更加生动形象的理解登陆界面和数据库的综合应用技术,所以,我们做出了学生信息管理系统! 二 设计思路... -
第二节 学生系统管理讨论与修改 150206118
2016-06-16 16:12:59通过学习学生信息管理系统软件,我了解到了基于函数的结构化大型程序的编写方法;了解到C语言管理软件的设计方法和编程思路。大概知道了编写的流程、要点还有一些基本命令。 首先,要明确编写的题目,也就是编写的... -
资产管理系统中的盘点表 设计思考(1)
2011-05-03 23:20:00在做一个资产管理系统,碰到资产盘点的设计和实现。整体是工作流。本人是大三学生,一直都处在很菜的程度上。第一次接触项目,碰到这个地方居然晕了。汗一个,流图已经有了,自己看半天看的晕了。晚上回来找找网上的... -
c++课程设计图书馆管理系统总结
2018-07-07 16:17:29从刚开始做图书馆管理系统到现在,经过了无数次的修改,由程序不成熟逐步的发展,更新,整个过程中,我得到了很多的收获,下面简单说一下自己的感悟:做任何一个程序,一开始必须要有一个总的规划,整体的思路必须在... -
基于java的家庭财务管理系统
2020-07-20 16:07:45该系统可以作为计算机专业学生的大作业,也可以作为毕业设计,代码中注释占有很高,方便参考者的学习,对学习框架,整体的思路有很大的帮助 -
嵌入式系统原理与设计.pdf
2012-12-05 22:27:22《嵌入式系统原理与设计》适合计算机、软件工程、电子、电气、机电一体化、光电等相关专业的研究生或本科高年级学生选作教材,同时也可作为从事嵌入式系统项目管理、整体设计和硬件、软件开发技术人员的参考书。 -
毕业设计(带论文)—试卷生成系统.rar
2020-05-23 21:52:13试卷生成模块是整个题库管理系统的核心。本系统的组卷是采用交互方式,即用户在输入各种要求后,系统会自动生成一份符合要求的试卷。组卷过程中系统会向用户依次询问以下信息: (1) 要生成的试卷满分分数 (2) ... -
自己动手写操作系统(含源代码).part2
2010-10-18 19:47:45首先是操作系统的名字改变了,原因在于虽然我们的试验性 OS从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix(本意为 TryMinix)改成了新名字... -
自己动手写操作系统(含源代码).part1
2010-10-18 19:41:25首先是操作系统的名字改变了,原因在于虽然我们的试验性 OS从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix(本意为 TryMinix)改成了新名字... -
语言程序设计课后习题答案
2012-12-27 17:02:37面向对象方法中的对象,是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位,由一组属性和一组行为构成。 面向对象的方法将数据及对数据的操作方法放在一起,作为一个相互依存、不可分离的整体--... -
c++软件开发心得
2019-06-22 16:18:11和上一个学期相比是完全不同的体验,开始进行了软件设计开发,在老师的引领下,尝试了几个简单的软件设计,有学生成绩管理系统、ATM机系统、通讯录还有最后的图书管理系统,在研究学习这几个系统的过程中,有了很多... -
ASP.NET精品课程+源代码
2009-01-05 20:15:51ASP.NET精品课程整体设计 一、 概述 《ASP.NET程序设计》课程是一门重要的计算机专业课,它是计算机网络、计算机软件及应用、计算机技术及应用、计算机信息管理、计算机网络管理及维护、电子商务、计算机多媒体技术... -
最权威的C++教程_C++_Primer_Plus中文第五版+C++_Primer中文第四版(都含源码+习题)(共4分卷)分卷1
2010-06-23 17:33:55本书在介绍C++特性的同时,讨论了基本C语言,使二者成为有机的整体。书中介绍了C++的基本概念, 并通过短小精悍的程序来阐明,这些程序都很容易复制和试验。还介绍了输入和输出、如何让程序执行重 复性任务、如何... -
最权威的C++教程_C++_Primer_Plus中文第五版+C++_Primer中文第四版(都含源码+习题)(共4分卷)分卷2
2010-06-23 17:47:19本书在介绍C++特性的同时,讨论了基本C语言,使二者成为有机的整体。书中介绍了C++的基本概念, 并通过短小精悍的程序来阐明,这些程序都很容易复制和试验。还介绍了输入和输出、如何让程序执行重 复性任务、如何... -
最权威的C++教程_C++_Primer_Plus中文第五版+C++_Primer中文第四版(都含源码+习题)(共4分卷)分卷3
2010-06-23 18:03:39本书在介绍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:223.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 创建对象的其他方式...