首先是对整体函数所需要的功能进行子函数的分类,让信息的输入,处理,输出,都可以进行模块化的设计.(需要全局代码的可直接下拉至文章末尾.)
******************************************************************************
文 件 名 : main.c
版 本 号 : 初稿
作 者 : 飘小叶
生成日期 : 2020年7月14日
最近修改 :
功能描述 : 学生信息管理系统
函数列表 :
* 1. Add_Information添加学生信息
* 2. Change_Information修改学生信息
* 3. Delete_Information删除学生信息
* 4. Head学生信息管理系统字符图标
* 5. Init学生信息管理系统初始化字符图标
* 6. isLogin判断是否登录成功
* 7. Students_Information学生信息
* 8. Login登录系统
* 9. main主函数
* 10. MainMenu主菜单界面
* 11. MenuSelect菜单选择
* 12. Quit退出程序或重新进入主菜单
* 13. Search_Information查询学生信息
* 14. Show_Information显示所有学生信息
* 15. Sort_Information对学生信息进行排序
* 16. StuManage学生信息管理系统 管理端字符图标
* 17. Swap交换两个学生信息
* 18. ReadData读取D:\\下的飘小叶_2220193789.txt文件
* 19. SaveData将链表中的数据存储在D:\\下的飘小叶_2220193789.txt文件
**设置头文件,宏定义账号:飘小叶,密码2220193789,设置枚举类型,结构体类型,文件操作时所需要的结点,以及各类的子函数声明。**
**在这里需要对枚举类型多说几句,大家可能对于枚举类型比较陌生,枚举类型enum,它所发挥的作用其实和#define相同,但是在进行多次宏定义的时候#define就会显得比较冗杂,于是便引入了枚举类型,例如:**
enum Day
{
Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
};
此时这个Day就是一种新的数据类型,而我的代码中出现的typedef enum Menu{...}MENU,这个其实就是给枚举型起了一个别名(外号).
```c
修改历史 :
1.日 期 : 2020年7月14日
作 者 : 飘小叶
修改内容 : 创建文件
******************************************************************************/
#include
#include
#include
#define MANAGER_NAME "飘小叶" //账号
#define MANAGER_PASSWORD "2220193789" //密码
typedef enum Menu
{
Exit,Lessons,Show,Add,Sort,Change,Delete,Search
}MENU;
typedef struct Student //类型首字母大写以和变量区分
{
int iIndex[50]; //学号
char cName[50]; //姓名
int iOlder[50]; //年龄
char cSex[5]; //性别
char cDatebirth[20]; //出生年月
char cAddress[50]; //地址
int iPhone[20]; //电话
char cMailbox[30]; //邮箱(E-mail)
struct Student *pNext;
}STU,*PSTU;
PSTU pHead = NULL;//学生信息头结点
PSTU pNew = NULL;//待添加学生信息
size_t iCount = 0;//学生总数
char UserName[10]; //用户名(账号)
char UserWord[10]; //密码
void Init(); //学生信息初始化
void MainMenu(); //主菜单界面
void StuManage(); //管理系统 管理端 字符图标
void Head();//管理系统字符图标
void Login();//登入系统
int isLogin();//判断是否登入成功
int MenuSelect(); //菜单选择
void ReadData();//读取数据
void SaveData();//保存数据
void Quit();//退出程序或重新进入主菜单
void Students_Information();
void Show_Information();
void Add_Information();
void Sort_Information();
void Change_Information();
void Delete_Information();
void Search_Information();
void Swap(PSTU stu1,PSTU stu2);
```
**设置主菜单界面,用Switch将其连接起来,首要原因就是Switch相比于近似作用的If来说的话,他的执行效率更高,并且在面向整个菜单界面的时候,分支化操作会使整个界面看起来更加的简洁,易懂。读到这里可能会用到后面几个函数的作用,Head()它就是个表头,起到美化界面的作用,Quit()就如整个注释里面写的那样,他就是一个退出并返回的作用,其次System("cls")冻屏函数,可以让屏幕停止在功能区所在的地方,便于下一步的操作和观察。**
```c
/*****************************************************************************
函 数 名 : MainMenu
功能描述 : 主菜单界面
输入参数 : 无
输出参数 : 无
返 回 值 : void
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2020年7月4日
作 者 : 飘小叶
修改内容 : 新生成函数
*****************************************************************************/
void MainMenu()
{
if (isLogin())
{
//登录成功
switch (MenuSelect())//菜单选择
{
case Exit://退出程序
system("cls");
Head(); //管理系统字符图标
Quit();//退出或返回主菜单
break;
case Lessons://学生信息
system("cls");
Students_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();
Show_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;
}
}
}
```
**Init(),就如同他的名字一样,他的作用就是初始化数据,首次登入的话需要将节点置空,初始化整个链表的数据,StuManage()和上面提到过的Head()是类似的作用,也是为了美化界面,而Login()就使用了前面提到过的宏定义账号密码的认定。**
```c
/*****************************************************************************
函 数 名 : Init
功能描述 : 学生信息管理系统初始化字符图标
输入参数 : 无
输出参数 : 无
返 回 值 : void
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2020年7月14日
作 者 : 飘小叶
修改内容 : 新生成函数
*****************************************************************************/
void Init()
{
/****************初始化数据****************/
pHead = (PSTU)malloc(sizeof(STU));
pHead->pNext = NULL;
SetConsoleTitle("学生信息管理系统(管理员)");
ReadData();
/****************载入界面*****************/
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();
}
```
**Head()和StuManage()的图像化操作,由几个简单的输出流语句构成。**
```c
//学生信息管理系统字符图标
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");
}
```
**登入系统函数,UserName和UseWord是刚开始进行的宏定义,其内的Sleep函数以毫秒为单位,将该函数的进程滞留一段时间进行演示,登陆成功的话,初始化才算是全部完成。
这里再和大家说一下Sleep()函数,Sleep()函数包含在#include里面,,它的功能就是将当前函数的功能挂起一段时间,其单位是毫秒,例如:Sleep(1000),就是让程序挂起来1000ms,也就是1s.
具有类似功能的还有usleep(),其单位是微秒,delay(),他的单位是微秒,但是它的作用是让当前程序的执行暂停一段时间.**
```c
/*****************************************************************************
函 数 名 : Login
功能描述 : 登录系统
输入参数 : 无
输出参数 : 无
返 回 值 : void
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2020年7月14日
作 者 : 飘小叶
修改内容 : 新生成函数
*****************************************************************************/
void Login()
{
StuManage();
char xing[] = { "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " };
for (int i = 0; i
{
printf("%c", xing[i]);
Sleep(10); //让该函数滞留10ms
}
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);//密码 2220193789
}
/*****************************************************************************
函 数 名 : isLogin
功能描述 : 判断是否登录成功
输入参数 : 无
输出参数 : 无
返 回 值 : int
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2020年7月14日
作 者 : 飘小叶
修改内容 : 新生成函数
*****************************************************************************/
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); //让该函数滞留1s(1000ms)
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;
}
```
**菜单选择界面,直观的让用户选出自己想要的功能,其内的c-‘0’是字符类型转整型的一种方法,用另一种说法来说的话,这个界面就是MainMenu的直观显示,二者的功能可以划=。
这里还需要提的是大家可能不太熟悉的getche()
getche()
头文件:#include 或 #include
该函数用于读取控制台输入的字符,并将输入的字符立即显示在控制台.
参数:该函数没有参数.
返回值:该函数从控制台读取字符,并在控制台显示读取的字符ASCII码值**
#include
void main()
{
char ch = getche(); /*读取字符*/
char ch2 = getche(); /*读取字符*/
printf("You put char is %c\n",ch);
printf("You put char is %c\n",ch2);
system("pause");
return;
}
如果用户输入as,则输出结果为:
as
You put char is a
You put char is s
例子运行后输入字符as就会出现这个结果。由于 getche()为阻塞形式运行,
所以在用户没有输入第二个字符的时候会继续等待&#