我一直以为学生信息管理系统是开源的,网上一搜一大把的那种。毕竟这种程序学完C之后都可以自己写一个,只有界面好看与否的问题。
最近好多学生问学生信息管理系统的代码,估计是C语言大作业什么的。然后我就去网上搜,不搜不知道啊,一搜吓一跳,要么运行报错99+,要么收费,还有那种给你一半代码,另一半代码加他付费索取的。
这周给大家带来免费开源版本的学生信息管理系统(管理员),也把我的设计思路分享一下。这次的代码实现了基本的增删改查功能,文件操作功能下周更新,到时候我会群发消息通知。
2
主体设计
int main()
{
Init(); //初始化
MainMenu(); //主界面
return 0;
}
初始化里面包括文件读取,管理员登录,数据的初始化等;
主界面是管理员登录之后实现各种功能模块化的重要界面,当功能实现之后退出回到的也是这个界面;
01
主界面MainMenu()
void MainMenu()
{
if (isLogin()) //判断是否登录成功
{
//登录成功
switch (MenuSelect()) //菜单选择
{
case Exit: //退出程序
system("cls");
Head();
Quit(); //退出或返回主菜单
break;
case Lessons: //课程信息
system("cls");
Lessons_Information();
Quit();
break;
case Show: //显示所有学生信息
system("cls");
Show_Information();
Quit();
break;
case Add: //添加学生信息
system("cls");
Add_Information();
Quit();
break;
case Sort: //对学生信息总分进行排序
system("cls");
Sort_Information();
Quit();
break;
case Change: //修改学生信息
system("cls");
Change_Information();
Quit();
break;
case Delete: //删除学生信息
system("cls");
Delete_Information();
Quit();
break;
case Search: //查询学生信息
system("cls");
Search_Information();
Quit();
break;
}
}
}
在这里梦凡用枚举将要实现的功能列举出来,然后对菜单选择的功能进行匹配
typedef enum Menu
{
Exit,Lessons,Show,Add,Sort,Change,Delete,Search
}MENU;
02
初始化 Init()
void Init()
{
/****************初始化数据****************/
pHead = (PSTU)malloc(sizeof(STU));
pHead->pNext = NULL;
SetConsoleTitle(L"学生信息管理系统(管理员)");
/****************载入界面*****************/
printf("欢迎使用本系统!\n");
int i;
printf("\n\n\n\n\n\n\n\n\t\t\t\t\t");
char heihei[] = { "即将进入学生管理系统..." };
for (i = 0; i < strlen(heihei); i++)
{
printf("%c", heihei[i]);
Sleep(10);
}
system("CLS");
StuManage();
system("cls");
Login();
}
初始化里面是对结构体的头结点进行内存分配初始化,以及载入界面,和登录界面的调用。
typedef struct Student //类型首字母大写以和变量区分
{
char cName[50];
char cNumber[50];
int iMath;
int iEnglish;
int iProgram;
int iScore;
struct Student *pNext;
}STU,*PSTU;
PSTU pHead = NULL; //信息学生头结点
PSTU pNew = NULL; //待添加学生信息
03
登录系统 Login()
void Login()
{
StuManage();
char xing[] = { "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " };
for (int i = 0; i<strlen(xing); i++)
{
printf("%c", xing[i]);
Sleep(10);
}
printf("\n\n\t\t\t\t\t\t请输入您的账号密码:\n\n\n\n\t\t\t\t\t\t账号:");
gets(UserName);
printf("\n\n\t\t\t\t\t\t密码:");
gets(UserWord);
}
在登录系统之前,梦凡先用宏定义对账号密码进行定义,全局变量设置存储账号密码的变量
#define MANAGER_NAME "DeRoy"
#define MANAGER_PASSWORD "666666"
char UserName[10];
char UserWord[10];
但是就这样让管理员输入密码,如果输入错误怎么办,别急,梦凡还进行了判断
int isLogin()
{
int times = 0; //密码输入次数
while (!(strcmp(UserName, MANAGER_NAME) == 0 && strcmp(UserWord, MANAGER_PASSWORD) == 0))
{
times++; //密码输入错误 times++
if (times > 3)
{
printf("\n\n\n\n\t\t\t\t账号或密码输入错误累计达到%d次,系统将于3秒后关闭", times);
Sleep(1000);
system("cls");
char shutdown[] = { "系统将于%d秒后关闭..." };
for (int i = 0; i < 3; i++)
{
printf(shutdown, 3 - i);
Sleep(1000);
system("cls");
}
exit(0);
}
printf("\n\n\n\n\t\t\t\t账号或密码输入错误,你还有%d次登录机会,按任意键重新登录...", 4 - times);
getch();
system("cls");
Login();
}
return 1;
}
账号密码输入错误达到4次将会在3秒之后退出系统,在账号密码输入错误的情况下再次调用Login()函数重新输入密码;
04
菜单选择 play()
int MenuSelect()
{
char c;
do
{
system("cls");
Head();
printf("\t\t\t\t ╭═════════════════════════════════○●○●═══╮\n");
printf("\t\t\t\t │ 学生信息管理系统 │\n");
printf("\t\t\t\t ╰═══○●○●═════════════════════════════════╯\n");
printf("\t\t\t\t ┌───────────────────────────────────────────-┐\n");
printf("\t\t\t\t │ │\n");
printf("\t\t\t\t │ 1. 课程安排 2. 显示数据 │\n");
printf("\t\t\t\t │ │\n");
printf("\t\t\t\t │ 3. 添加数据 4. 数据排名 │\n");
printf("\t\t\t\t │ │\n");
printf("\t\t\t\t │ 5. 修改数据 6. 删除数据 │\n");
printf("\t\t\t\t │ │\n");
printf("\t\t\t\t │ 7. 查询数据 0. 退出程序 │\n");
printf("\t\t\t\t │ │\n");
printf("\t\t\t\t └────────────────────────────────────────────┘\n");
printf("\t\t\t\t\t\t 请您选择(0-7):");
c = getche();
} while (c < '0' || c > '7');
return c - '0';
}
这里梦凡用do{}while();循环,先输入选择的功能,再判断输入的功能是否是我给出的功能,然后返回这个功能对应的值,字符转数字;
05
各功能的实现
现在已经登录了系统,菜单也给出来了,现在只要实现各个菜单相对应的功能就可以了
需要实现的功能:
void Quit();//退出
void Lessons_Information();//课程信息
void Show_Information();//显示学生信息
void Add_Information();//添加学生信息
void Sort_Information();//对成绩进行排序
void Change_Information();//修改学习信息
void Delete_Information();//删除学生信息
void Search_Information();//查询学生信息
这八个基本功能,实现完了学生信息管理系统就基本大功告成。
3
功能实现
由于代码相似度很高,我就只介绍几个有代表性的功能,其他功能看源代码,我注释量还是可以的。
void Add_Information()
{
Head();
/************添加学生信息***********/
pNew = (PSTU)malloc(sizeof(STU));
printf("\t\t\t\t\t\t添加学生信息:\n\n\n\n\t\t\t\t\t\t学号:");
scanf("%s", pNew->cNumber);
printf("\n\t\t\t\t\t\t姓名:");
scanf("%s", pNew->cName);
printf("\n\t\t\t\t\t\t高等数学:");
scanf("%d", &pNew->iMath);
printf("\n\t\t\t\t\t\t大学英语:");
scanf("%d", &pNew->iEnglish);
printf("\n\t\t\t\t\t\t程序设计:");
scanf("%d", &pNew->iProgram);
pNew->iScore = pNew->iEnglish + pNew->iMath + pNew->iProgram;
pNew->pNext = pHead->pNext;
pHead->pNext = pNew;
pNew = NULL;
iCount++;
}
这里我用的是单链表的头插法
首先给新成员分配内存 pNew = (PSTU)malloc(sizeof(STU));
然后用户输入学生信息,计算总分
头插法主要是不能破坏链表的链式结构,要首尾相连
要插入的新节点的pNext指向头结点的pNext pNew->pNext = pHead->pNext;
然后头结点的下一个节点指向要插入的节点 pHead->pNext = pNew;
void Delete_Information()
{
Head();
char ID[10];
char operate;
printf("\t\t\t\t\t\t删除学生信息:\n\n\n");
printf("\t\t\t\t\t\t请输入学生学号:");
scanf("%s", ID);
//遍历学生信息
PSTU pCurrent = pHead; //指向头结点
while (pCurrent->pNext != NULL) //遍历输出所有学生
{
if (strcmp(pCurrent->pNext->cNumber, ID) == 0)
{
//信息库里面有要删除的学生信息
printf("\n\n\n\t\t\t\t\t要删除的学生信息...\n\n");
printf("\n\n\t\t\t\t\t学号\t姓名\t高数\t英语\t程序设计\t总分\n\n");
printf("\t\t\t\t\t %s\t %s\t %d\t %d\t %d\t\t%d\n",pCurrent->pNext->cNumber,
pCurrent->pNext->cName, pCurrent->pNext->iMath, pCurrent->pNext->iEnglish
, pCurrent->pNext->iProgram,pCurrent->pNext->iScore);
printf("\n\n\n\t\t\t\t\t是否删除该学生信息(y/Enter):");
operate = getch();
if (operate == 'y' || operate == 'Y' || operate == 13) //13是回车键Enter的ASCII值
{
//删除学生信息
PSTU pTemp = pCurrent->pNext; //定义PSTU指针 pTemp 指向要删除的节点
pCurrent->pNext = pTemp->pNext;
free(pTemp);
iCount--;
printf("\n\n\n\t\t\t\t\t删除成功...\n\n");
return;
}
else{
printf("\n\n\n\t\t\t\t\t删除失败...\n\n");
return;
}
}
pCurrent = pCurrent->pNext; //指向下一个节点
}
printf("\n\n\n\n\t\t\t\t\t 没有找到要删除的学生信息......\n\n");
}
在删除学生信息的功能里面,定义当前节点指向头结点,而不是第一个数据节点,除了防止没有学生数据的时候误按删除数据出现小bug外,主要是删除节点的时候要保证首尾相连,单链表只知道下一个节点是谁,你必须知道要删除的节点的上一个节点是那个节点,只有这样删除的时候才能保证点链表首尾相连
void Sort_Information()
{
Head();
if (iCount < 2) //一个学生不需要排序
{
system("cls");
Show_Information();
return;
}
//从大到小排序 冒泡排序
PSTU pCurrent,pTemp;
STU Temp;
for (pCurrent = pHead->pNext; pCurrent != NULL; pCurrent = pCurrent->pNext)
{
for (pTemp = pCurrent->pNext; pTemp != NULL; pTemp = pTemp->pNext)
{
if (pCurrent->iScore < pTemp->iScore)
{
Swap(&Temp, pCurrent);
Swap(pCurrent, pTemp);
Swap(pTemp, &Temp);
}
}
}
system("cls");
Show_Information();
}
数据处理:
void Swap(PSTU stu1, PSTU stu2)
{
strcpy(stu1->cName, stu2->cName);
strcpy(stu1->cNumber, stu2->cNumber);
stu1->iEnglish = stu2->iEnglish;
stu1->iMath = stu2->iMath;
stu1->iProgram = stu2->iProgram;
stu1->iScore = stu2->iScore;
}
梦凡准备在发数据结构文章的时候将十大排序方法总结一下,所以在这个排序函数里面我用的是最简单的,也是入门的排序方法:冒泡排序。
梦凡之前有保存过这样一个表情包,觉得理解起来还不错,就收藏了,今天终于用上了
4
函数说明
在这个学生信息管理系统里面我为了区别我的程序,让我的程序独一无二,我加了很多带动画效果的字符串,还有一些图标字符串。
虽然代码量增加了,但是效果是不错的。界面觉得ok,毕竟是控制台程序,我还给这个学生信息管理系统加了一个log,感觉像那么回事。
我用到的图标字符串函数
void Head()
{
printf("\n");
printf("\t\t\t\t\t╭ % ╮ ╭ ```╮ \n");
printf("\t\t\t\t\t(@^o^@) 学生信息管理系统 (⌒:⌒)\n");
printf("\t\t\t\t\t(~):(~) (~)v(~) \n");
printf("\n\n\n");
}
登录界面的管理员图标
void StuManage()
{
printf("\n");
printf("\t\t\t\t\t╭ % ╮ ╭ ```╮ \n");
printf("\t\t\t\t\t(@^o^@) 学生信息管理系统 管理端(⌒:⌒)\n");
printf("\t\t\t\t\t(~):(~) (~)v(~) \n");
printf("\n\n\n");
}
5
优化设计
能优化的地方那可就多了,我暂时是简单地实现了各个功能函数。
在这些函数里面缺少很多约束条件,像那个账号密码是否符合输入标准,成绩符合100分制还是150分制;
最主要的是文件读写功能没实现,这个下周我会对源程序和源代码进行更新,更新之后会通知大家。