工作环境:VISUAL STUDIO 2017
以下为代码部分
本代码仅供学习用途,禁止照搬照抄!
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
#include<String.h>
#include<ctype.h>//包含数字,字母判断的函数
typedef struct The_users { //typedef 可以定义结构体别名
char name[100]; //账号,为了防止数组越界将数组范围定义更大一些
char pwd[100]; //密码
char phone[100]; //手机号
int situation; //状态值
} Users; //该结构体别名
//以下为打印菜单部分函数
void Option2(int); //学生菜单switch
void Register(); //学生注册模块
void Login(); //学生登录模块
void ReadaFile(char *filename);//文件初始化
void Login2();//老师登陆模块
void Register2();//老师注册模块
void Option3(int option);//老师菜单switch
void caidan3();//打印菜单-教师端
void caidan1();//打印菜单-选择端
void caidan2();//打印菜单-学生端
void Option1(int option);//总菜单switch
char Stuname[10] = { 'S', 'u', 's', 'e', 'r', 's', '.', 't', 'x', 't' }; //学生文档路径
char Teachername[10] = { 'T', 'u', 's', 'e', 'r', 's', '.', 't', 'x', 't' }; //老师文档路径
void Lockzhanghao(char *filename, Users b);//3次锁号函数,有bug未能实现
void gongneng2();//教师端功能
void gongneng();//学生端功能
void gongnengswitch2(int option);//教师端switch
void gongnengswitch(int option);//学生端switch
//以下为系统功能实现部分的函数
void printBubblesort2(struct Node* StudentNode);
struct Node* SearchNode2(struct Node* StudentNode, char* name);
void PrintAverage80(struct Node* StudentNode);
void PrintAverage(struct Node* StudentNode);//计算并打印平均数
void printBubblesort(struct Node* StudentNode);//冒泡排序
void InsertNode();
struct Node* CreatNode();//创建头结点
struct Node* CreatNewNode(struct Student data);//创建新结点
void CreatNodeList(struct Node* HeadNode, struct Student data);
void deletestudent();
void deletenode(struct Node* headnode, char* name);
struct Node* SearchNode(struct Node* StudentNode, char* name);
void PrintNode(struct Node* StudentNode);
void PrintList(struct Node* StudentNode);
void ReadFromFile(char* filename, struct Node* StudentNode);
void SaveFile1(char* filename, struct Node* StudentNode);
struct Node* StudentNode;//学生信息节点StudentNode(结构体变量),本程序该全局变量作为头节点
char S1[5] = { 's','.','t','x','t' };//文件的保存路径
//以下为封面函数
void welcome();//打印封面
void cursor(int x, int y);//定位光标
void Windowstime();//获得电脑时间
void AppearCursor();//光标出现
void HideCursor();//隐藏光标
void PrintExit();//退出封面
struct Student {//定义学生信息(结构体类型)
char name[20];//姓名
char sex[20];//性别
char number[20];//学号
float grade1;//第一科
float grade2;//第二科
float grade3;//第三科
};
struct Node {//定义学生信息节点(结构体类型)
struct Student data;//数据域
struct Node* Next;//指针域
};
int i = 0, flag = 1, menu = 0;
int main() {//主函数
welcome();
system("cls");
AppearCursor();
caidan1();//主函数只有菜单1,然后在各个嵌套函数中实现功能
}
void ReadaFile(char *filename) {//创建/判断是否有文件生成
FILE* fp = fopen(filename, "r");
if (fp == NULL) {
fp = fopen(filename, "w");
}
fclose(fp);
}
//通过Option2函数接收代表功能对应的数字来调用其他功能函数
void Option2(int option) {//学生菜单
switch (option) {
case 1:
Login();
break;
case 2:
Register();
break;
case 3:
system("cls");
caidan1();
//return;
//flag = 0; //flag置0,结束主函数循环(也可以不要此句)
exit(0);
}
}
/*
注册账号模块
*/
void Register() {
system("cls");//换页
Users a, b; //定义两个临时用结构体变量,a用于写入文件
a.situation = 0;
FILE *fp;
char temp_pwd[20];
//int count = 0;
printf("\n\t\t欢迎来到注册界面!\n");
printf("____________________________________________________________________\n");
printf("[注册要求]");
printf("\n\n\t\t(1) 用户名必须为英文字母或英文字母+数字,总长度不超过8个字符\n\n");
printf("\t\t(2) 密码不低于6位,总长度不超过10个字符\n\n");
printf("____________________________________________________________________");
fp = fopen("Susers.txt", "r");
fread(&b, sizeof(Users), 1, fp); //读入一个用户信息,用于在下面查找注册的账号名是否存在
printf("\n\t\t请设置账号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
scanf("%s", a.name);//这里有个bug,会导致数组越界
while (1) {
int len_name = strlen(a.name);
int count = 0;//遍历数字长度
for (int j = 0; j < len_name; j++) {
if (isdigit(a.name[j])) { //判断账号是否仅由纯数字组成
count++;
}
}
if (count == len_name) {
printf("\t\t非法用户名 !请重新注册!\n");//如果由纯数字组成,则返回
Sleep(1000);
fclose(fp);
system("cls");
return;
}
if (len_name > 8) {
printf("\t\t非法用户名 !请重新注册!\n");//不能输入中文符号,不然会导致程序重启
Sleep(1000);
fclose(fp);
system("cls");
return;
}
for (int j = 0; j < len_name; j++) {
if (!isalnum(a.name[j])) { //判断是否仅由字母与数字组成账号长度
printf("\t\t非法用户名 !请重新注册!\n");//不能输入中文符号,不然会导致程序重启
Sleep(1000);
fclose(fp);
system("cls");
return;
}
}
if (strcmp(a.name, b.name)) { //如果注册账号不存在
if (!feof(fp)) { //如果未到文件尾
fread(&b, sizeof(Users), 1, fp); //继续读入下一个用户信息
}
else {
break; //检查完毕,跳出
}
}
else { //如果此账号已存在,退出
printf("\t\t此用户名已存在!请重新注册!\n");
Sleep(1000);
fclose(fp);
system("cls");
return;
}
}
printf("\t\t请输入您的手机号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
scanf("%s", a.phone);
int time = 2;
do {
printf("\t\t请设置密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
i = 0;
/*
以下代码段用于将输入的明文替换为'*'
起到保护作用,但仍存一点bug
*/
do {
a.pwd[i] = _getch();
if (a.pwd[i] == '\r')
break;
if (a.pwd[i] == '\b') {//如果退格
if (i == 0) {
printf("\a");
continue;
}
i = i - 1;
printf("\b");
}
else {
i = i + 1;
printf("*");
}
} while (a.pwd[i] != '\n'); //当接收到回车符时完成密码接收
a.pwd[i] = '\0';//遍历后的结束位
int len_password = strlen(a.pwd);
if (len_password < 6 || len_password>10) {
printf("\n\t\t密码输入格式错误!请重新注册!\n");
Sleep(1000);
fclose(fp);
system("cls");
return;
break;
}
printf("\n");
printf("\t\t请确认密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
/*
再接收一次密码
用于验证,防止用户设置密码出错
*/
i = 0;
do {
temp_pwd[i] = _getch();
if (temp_pwd[i] == '\r')
break;
if (temp_pwd[i] == '\b') {
if (i == 0) {
printf("\a");
continue;
}
i = i - 1;
printf("\b");
}
else {
i = i + 1;
printf("*");
}
} while (temp_pwd[i] != '\n');
temp_pwd[i] = '\0';
printf("\n");
if (!strcmp(a.pwd, temp_pwd)) { //如果两次输入的密码相同就可以注册了
fp = fopen("Susers.txt", "a"); // a-向文件尾部追加写入
fwrite(&a, sizeof(Users), 1, fp);//二进制输入
printf("\t\t账号注册成功!\n");
Sleep(1000);
fclose(fp);
system("cls");
return;
}
else {
if (time != 0) {
printf("\n\t\t两次输入的密码不相同!\t请重新输入(剩余%d次机会)\n", time);
time--;
continue; //如果本次密码匹配不相同跳出,进入下一次输入
}
else {
printf("\n\t\t多次输入错误,即将退出!");
Sleep(1000);
fclose(fp);
system("cls");
return;
}
}
} while (time >= 0);
}
/*
学生登录模块
*/
void Login() {
system("cls");//换页
Users a, b; //定义结构体The_users别名
FILE *fp;
printf("\t\t\n欢迎来到登录界面!\n\n");
printf("\t\t请输入账号/手机号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
scanf("%s", a.name);//a是用户输入的账户
int len_name = strlen(a.name);
for (int j = 0; j <= len_name; j++) {
a.phone[j] = a.name[j];//将输入值赋值给phone
}
printf("\t\t请输入密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
i = 0;
/*
采用相同的方法掩盖明文密码
*/
do {
a.pwd[i] = _getch();
if (a.pwd[i] == '\r')
break;
if (a.pwd[i] == '\b') {
if (i == 0) {
printf("\a");
continue;
}
i = i - 1;
printf("\b");
}
else {
i = i + 1;
printf("*");
}
} while (a.pwd[i] != '\n' && i < 20);
a.pwd[i] = '\0';//遍历后的结束位
printf("\n");
fp = fopen("Susers.txt", "r+b");
while (1) {
fread(&b, sizeof(Users), 1, fp); //读入一个结构体字符块 写入b
if ((strcmp(a.name, b.name) == 0) && (!feof(fp))) { //如果有此账号
break; //此账号已经注册 可以登录
}
else {
if ((strcmp(a.phone, b.phone) == 0) && (!feof(fp))) {
break;
}
else {
if (!feof(fp)) { //如果文件没有读完
continue;
}
else {
printf("\t\t账号/手机号或密码错误!\n");
fclose(fp);
Sleep(1000);
system("cls");
return;
}
}
}
}
if (b.situation != 3) {//如果没有输错3次
if (strcmp(a.pwd, b.pwd) == 0) { /*如果密码匹配*/
system("cls");
printf("\t\t登录成功!欢迎使用!\n");
Sleep(1000);
fclose(fp);
system("cls");
gongneng();
}
else {
printf("\t\t账号或密码错误!……\n");
fclose(fp);
// Lockzhanghao(Stuname,b);//3次锁号函数,有bug已停用
Sleep(1000);
system("cls");
return;
}
}
else {
printf("\t\t由于密码输错3次,该账号已锁定!……");
fclose(fp);
Sleep(1000);
system("cls");
return;
}
}
void caidan3() {
while (flag) {
ReadaFile(Teachername);
do {
printf("-----------------------------教师端-学生信息管理系统登陆界面--------------------------------------\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("-----------------------------------------------------------------------------------\n");
printf("\n");
printf("\t\t\t\t 请输入选项:[\t]\b\b\b\b\b");
scanf("%d", &menu);
if (menu > 3 || menu < 1) {
printf("输入错误,请重新输入!");
Sleep(1000);
system("cls");
}
} while (menu > 3 || menu < 1);
Option3(menu);
}
}
void caidan1() {
while (flag) {
do {
//cursor(34, 8);
printf("-----------------------------学生信息管理系统登陆界面--------------------------------------\n");
//cursor(53, 12);
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("-----------------------------------------------------------------------------------\n");
printf("\n");
//cursor(28, 16);
printf("\t\t\t\t 请输入选项:[\t]\b\b\b\b\b");
scanf("%d", &menu);
if (menu > 3 || menu < 1) {
printf("输入错误,请重新输入!");
Sleep(1000);
system("cls");
}
} while (menu > 3 || menu < 1);
Option1(menu);
}
}
void Option1(int option) {//主菜单
switch (option) {
case 1:
system("cls");//换页
caidan2();
break;
case 2:
system("cls");//换页
caidan3();
break;
case 3:
system("cls");
printf("\n\t\t谢谢使用!\n");
//flag = 0; //flag置0,结束主函数循环(也可以不要此句)
PrintExit();
exit(0);
}
}
//通过Option3函数接收代表功能对应的数字来调用其他功能函数
void Option3(int option) {//老师菜单
switch (option) {
case 1:
Login2();
break;
case 2:
Register2();
break;
case 3:
system("cls");
caidan1();
//return ;
//flag = 0; //flag置0,结束主函数循环(也可以不要此句)
}
}
/*
注册账号模块
*/
void Register2() {
system("cls");//换页
Users a, b; //定义两个临时用结构体变量,a用于写入文件
a.situation = 0;
FILE *fp;
char temp_pwd[20];
//int count = 0;
printf("\n\t\t欢迎来到注册界面!\n");
printf("____________________________________________________________________\n");
printf("[注册要求]");
printf("\n\n\t\t(1) 用户名必须为英文字母或英文字母+数字,总长度不超过8个字符\n\n");
printf("\t\t(2) 密码不低于6位,总长度不超过10个字符\n\n");
printf("____________________________________________________________________");
printf("\n\t\t请设置账号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
fp = fopen("Tusers.txt", "r");
fread(&b, sizeof(Users), 1, fp); //读入一个用户信息,用于在下面查找注册的账号名是否存在
scanf("%s", a.name);
while (1) {
int len_name = strlen(a.name);//接受字符串长度
int count = 0;//遍历数字长度
for (int j = 0; j < len_name; j++) {
if (isdigit(a.name[j])) { //判断账号是否仅由纯数字组成
count++;
}
}
if (count == len_name) {
printf("\t\t非法用户名 !请重新注册!\n");
Sleep(1000);
fclose(fp);
system("cls");
return;
}
if (len_name > 8) {
printf("\t\t非法用户名 !请重新注册!\n");
Sleep(1000);
fclose(fp);
system("cls");
return;
}
for (int j = 0; j < len_name; j++) {
if (!isalnum(a.name[j])) { //判断是否仅由字母与数字组成与账号长度
printf("\t\t非法用户名 !请重新注册!\n");//不能输入中文符号,不然会导致程序重启
Sleep(1000);
fclose(fp);
system("cls");
return;
}
}
if (strcmp(a.name, b.name)) { //如果注册账号不存在
if (!feof(fp)) { //如果未到文件尾
fread(&b, sizeof(Users), 1, fp); //继续读入下一个用户信息
}
else {
break; //检查完毕,跳出
}
}
else { //如果此账号已存在,退出
printf("\t\t此用户名已存在!请重新注册!\n");
Sleep(1000);
fclose(fp);
system("cls");
return;
}
}
printf("\t\t请输入您的手机号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
scanf("%s", a.phone);
int time = 2;
do {
printf("\t\t请设置密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
i = 0;
/*
以下代码段用于将输入的明文替换为'*'
起到保护作用,但仍存一点bug
*/
do {
a.pwd[i] = _getch();
if (a.pwd[i] == '\r')
break;
if (a.pwd[i] == '\b') {//如果退格
if (i == 0) {
printf("\a");
continue;
}
i = i - 1;
printf("\b");
}
else {
i = i + 1;
printf("*");
}
} while (a.pwd[i] != '\n' && i < 20); //当接收到回车符或者密码长度已够时完成密码接收
a.pwd[i] = '\0';//遍历后的结束位(很重要)
int len_password = strlen(a.pwd);
if (len_password < 6 || len_password>10) {
printf("\n\t\t密码输入格式错误!请重新注册!\n");
Sleep(1000);
fclose(fp);
system("cls");
return;
break;
}
printf("\n");
printf("\t\t请确认密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
/*
再接收一次密码
用于验证,防止用户设置密码出错
*/
i = 0;
do {
temp_pwd[i] = _getch();
if (temp_pwd[i] == '\r')
break;
if (temp_pwd[i] == '\b') {
if (i == 0) {
printf("\a");
continue;
}
i = i - 1;
printf("\b");
}
else {
i = i + 1;
printf("*");
}
} while (temp_pwd[i] != '\n' && i < 20);
temp_pwd[i] = '\0';
printf("\n");
if (!strcmp(a.pwd, temp_pwd)) { //如果两次输入的密码相同就可以注册了
fp = fopen("Tusers.txt", "a"); // a-向文件尾部追加写入
fwrite(&a, sizeof(Users), 1, fp);//二进制输入
printf("\t\t账号注册成功!\n");
Sleep(1000);
fclose(fp);
system("cls");
return;
}
else {
if (time != 0) {
printf("\n\t\t两次输入的密码不相同!\t请重新输入(剩余%d次机会)\n", time);
time--;
continue; //如果本次密码匹配不相同跳出,进入下一次输入
}
else {
printf("\n\t\t多次输入错误,即将退出!");
Sleep(1000);
fclose(fp);
system("cls");
return;
}
}
} while (time >= 0);
}
/*
教师登录模块
*/
void Login2() {
system("cls");//换页
Users a, b; //定义结构体The_users别名
FILE *fp;
printf("\t\t\n欢迎来到登录界面!\n\n");
printf("\t\t请输入账号/手机号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
scanf("%s", a.name);//a是用户输入的账户
int len_name = strlen(a.name);
for (int j = 0; j <= len_name; j++) {
a.phone[j] = a.name[j];//将输入值赋值给phone
}
printf("\t\t请输入密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
i = 0;
/*
采用相同的方法掩盖明文密码
*/
do {
a.pwd[i] = _getch();
if (a.pwd[i] == '\r')
break;
if (a.pwd[i] == '\b') {
if (i == 0) {
printf("\a");
continue;
}
i = i - 1;
printf("\b");
}
else {
i = i + 1;
printf("*");
}
} while (a.pwd[i] != '\n' && i < 20);
a.pwd[i] = '\0';//遍历后的结束位
printf("\n");
fp = fopen("Tusers.txt", "r+b");
while (1) {
fread(&b, sizeof(Users), 1, fp); //读入一个结构体字符块 写入b
if ((strcmp(a.name, b.name) == 0) && (!feof(fp))) { //如果有此账号
break; //此账号已经注册 可以登录
}
else {
if ((strcmp(a.phone, b.phone) == 0) && (!feof(fp))) {
break;
}
else {
if (!feof(fp)) { //如果文件没有读完
continue;
}
else {
printf("\t\t账号/手机号或密码错误!\n");
fclose(fp);
Sleep(1000);
system("cls");
return;
}
}
}
}
if (b.situation != 3) {//如果没有输错3次
if (strcmp(a.pwd, b.pwd) == 0) { /*如果密码匹配*/
system("cls");
printf("\t\t登录成功!欢迎使用!\n");
Sleep(1000);
fclose(fp);
system("cls");
gongneng2();
}
else {
printf("\t\t账号或密码错误!……\n");
fclose(fp);
// Lockzhanghao(Teachername,b);//3次锁号函数,有bug已停用
Sleep(1000);
system("cls");
return;
}
}
else {
printf("\t\t由于密码输错3次,该账号已锁定!……");
fclose(fp);
Sleep(1000);
system("cls");
return;
}
}
void caidan2() {
while (flag) {
ReadaFile(Stuname);
do {
printf("-----------------------------学生端-学生信息管理系统登陆界面--------------------------------------\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("-----------------------------------------------------------------------------------\n");
printf("\n");
printf("\t\t\t\t 请输入选项:[\t]\b\b\b\b\b");
scanf("%d", &menu);
if (menu > 3 || menu < 1) {
printf("输入错误,请重新输入!");
Sleep(1000);
system("cls");
}
} while (menu > 3 || menu < 1);
Option2(menu);
}
}
void Lockzhanghao(char *filename, Users b) {//账号锁定,有bug已停用,结构体数组和结构体两种数据格式不能
Users a[100];
FILE *fp;
fp = fopen(filename, "r");
int count = 0;
while (1) {
fread(&a[count], sizeof(Users), 1, fp);
if (!feof(fp)) { //如果文件没有读完
if (a[count].name == b.name) {
a[count].situation++;
printf("\n\n%d", a[count].situation);
}
count++;
continue;
}
else {
fclose(fp);
break;
}
}
fp = fopen(filename, "w");
fclose(fp);//清空文件
fp = fopen(filename, "w");
for (int j = 0; j < count; j++) {
fwrite(&a[count], sizeof(Users), 1, fp);
}
fclose(fp);
}
void gongneng2() {//教师端功能
while (flag) {
StudentNode = CreatNode();//创建链表(表头),使得StudentNode成为表头
ReadFromFile(S1, StudentNode);//读入之前的文件信息
do {
printf("-----------------------------教师端-学生信息管理系统--------------------------------------\n");
printf("\t\t\t\t1.添加某学生信息\n");//1.添加某学生信息(学号、姓名、性别、三科成绩) 2.学生基本信息输出 3.按学号查询学生信息
printf("\t\t\t\t2.学生基本信息输出\n");//4.按学号修改某学生信息 5.求每个人平均成绩并输出 6.删除某学生信息
printf("\t\t\t\t3.按学号查询学生信息\n");//7.输出平均分为80分以上的同学信息 8.将学生总分由小到大排序 9.退出
printf("\t\t\t\t4.按学号修改某学生信息\n");//----------------------------------------------------------------
printf("\t\t\t\t5.求每个人平均成绩并输出\n");//学生端 1.查询本人成绩 2.按姓名查询成绩 3.查找所有学生总成绩综合排名 4.输出平均分为80分以上的同学信息 5.退出
printf("\t\t\t\t6.删除某学生信息\n");
printf("\t\t\t\t7.输出平均分为80分以上的同学信息\n");
printf("\t\t\t\t8.将学生总分由小到大排序\n");
printf("\t\t\t\t9.退出\n");
printf("-----------------------------------------------------------------------------------\n");
printf("\n");
printf("\t\t\t\t 请输入选项:[\t]\b\b\b\b\b");
scanf("%d", &menu);
if (menu > 9 || menu < 1) {
printf("输入错误,请重新输入!");
Sleep(1000);
system("cls");
}
} while (menu > 9 || menu < 1);
gongnengswitch2(menu);
}
}
void gongneng() {//学生端功能
while (flag) {
StudentNode = CreatNode();//创建链表(表头),使得StudentNode成为表头
ReadFromFile(S1, StudentNode);//读入之前的文件信息
do {
printf("-----------------------------学生端-学生信息管理系统--------------------------------------\n");
//1.添加某学生信息(学号、姓名、性别、三科成绩) 2.学生基本信息输出 3.按学号查询学生信息
printf("\t\t\t\t1.按姓名查询成绩\n");//4.按学号修改某学生信息 5.求每个人平均成绩并输出 6.删除某学生信息
printf("\t\t\t\t2.查找所有学生总成绩综合排名\n");//7.输出平均分为80分以上的同学信息 8.将学生总分由小到大排序 9.退出
printf("\t\t\t\t3.输出平均分为80分以上的同学信息\n");//----------------------------------------------------------------
printf("\t\t\t\t4.退出\n");//学生端 1.查询本人成绩 2.按姓名查询成绩 3.查找所有学生总成绩综合排名 4.输出平均分为80分以上的同学信息 5.退出
printf("-----------------------------------------------------------------------------------\n");
printf("\n");
printf("\t\t\t\t 请输入选项:[\t]\b\b\b\b\b");
scanf("%d", &menu);
if (menu > 5 || menu < 1) {
printf("输入错误,请重新输入!");
Sleep(1000);
system("cls");
}
} while (menu > 5 || menu < 1);
gongnengswitch(menu);
}
}
void gongnengswitch2(int option) {//对应的switch选项实现
struct Student s;
switch (option) {
case 1://已实现
system("cls");
InsertNode();
SaveFile1(S1, StudentNode);//保存文件(路径,头节点)
printf("插入操作执行完成!-------------");
Sleep(1000);
system("cls");
return;
case 2://已实现
system("cls");
printf("\t【浏览信息】\n");
PrintNode(StudentNode);//链表输出
printf("浏览操作执行完成--------------");
Sleep(1000);
system("cls");
return;
case 3://已实现
system("cls");
printf("\t【查找信息】\n");
printf("请输入查找的学号:");
scanf("%s", s.name);
if (SearchNode(StudentNode, s.name) == NULL) {
printf("未找到相关信息!\n");
Sleep(1000);
system("cls");
}
else
{
PrintList(SearchNode(StudentNode, s.name));
printf("查找操作执行完成---------------");
system("pause");
system("cls");
return;
}
break;
default:printf("输入数据有误,重新输入\n");
Sleep(1000);
system("cls");
return;
case 4://已实现
system("cls");
printf("\t【更改信息】\n");
printf("请输入更改的学号:");
scanf("%s", s.name);
if (SearchNode(StudentNode, s.name) == NULL) {
printf("未找到相关信息!\n");
}
else
{
struct Node* s1 = SearchNode(StudentNode, s.name);
printf("请输入新的学生信息");
printf("请输入同学姓名,性别,学号,三科成绩");
scanf("%s%s%s%f%f%f", s1->data.name, s1->data.sex, s1->data.number, &s1->data.grade1, &s1->data.grade2, &s1->data.grade3);
printf("修改操作执行完成--------------");
SaveFile1(S1, StudentNode);//保存文件
}
Sleep(1000);
system("cls");
return;
case 5://已实现
system("cls");
printf("姓名\t性别\t学号\t平均成绩\n");//打印标题
PrintAverage(StudentNode);
system("pause");
system("cls");
return;
case 6://已实现
system("cls");
printf("\t【删除信息】\n");
deletestudent();
SaveFile1(S1, StudentNode);//保存文件
printf("删除操作执行完成---------------");
Sleep(1000);
system("cls");
return;
case 7://已实现
system("cls");
printf("姓名\t性别\t学号\t平均成绩\n");//打印标题
PrintAverage80(StudentNode);
system("pause");
system("cls");
return;
case 8://已实现
system("cls");
printBubblesort(StudentNode);
system("pause");
system("cls");
return;
case 9://已实现
system("cls");
printf("\n\t\t谢谢使用!\n");
Sleep(1000);
system("cls");
caidan1();
}
}
void gongnengswitch(int option) {//对应的switch选项实现
struct Student s;
switch (option) {
case 1://按名字查询成绩(已实现)
system("cls");
printf("\t【查找信息】\n");
printf("请输入查找的名字:");
scanf("%s", s.name);
if (SearchNode2(StudentNode, s.name) == NULL) {
printf("未找到相关信息!\n");
}
else
{
PrintList(SearchNode2(StudentNode, s.name));
printf("查找操作执行完成---------------");
}
system("pause");
system("cls");
return;
case 2://查看所有学生总成绩综合排名(从大到小排名)(已实现)
system("cls");
printBubblesort2(StudentNode);
system("pause");
system("cls");
return;
case 3://输出平均分大于80分同学成绩(已实现)
system("cls");
printf("姓名\t性别\t学号\t平均成绩\n");//打印标题
PrintAverage80(StudentNode);
system("pause");
system("cls");
return;
case 4:
system("cls");
printf("\n\t\t谢谢使用!\n");
Sleep(1000);
system("cls");
caidan1();
}
}
//以下为功能实现部分的函数
void InsertNode() {//插入函数
int x;
struct Student S;//数据域
printf("请输入学生个数\n");
scanf("%d", &x);
for (int i = 1; i <= x; i++) {//i作遍历,x为学生数
printf("请输入第%d个同学姓名,性别,学号,以及三科成绩\n", i);
scanf("%s%s%s%f%f%f", S.name, S.sex, S.number, &S.grade1, &S.grade2, &S.grade3);//这样写会有bug,因为一旦有数据格式非法输入就会导致数据栈损坏
CreatNodeList(StudentNode, S);//将StudentNode头节点和数据域生成的结点连接起来
}
}
struct Node* CreatNode() //建立头节点(建立链表)
{
struct Node* HeadNode = (struct Node*)malloc(sizeof(struct Node));
HeadNode->Next = NULL;
return HeadNode;//返回表头(头节点),本程序是用StudentNode接收头节点,也可以传节点进来在函数中接收,返回StudentNode头节点
}
struct Node* CreatNewNode(struct Student data) {//建立新结点函数
struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));//新节点创建
NewNode->data = data;//将数据域变成一个结点
NewNode->Next = NULL;
return NewNode;//注意!该函数在CreatNodeList(插入节点)函数里面使用,不单独使用
}
void CreatNodeList(struct Node* HeadNode, struct Student data) {//将数据域(结构体)变成一个节点并实现节点连接
struct Node* NewNode = CreatNewNode(data);//将数据域变成一个结点
NewNode->Next = HeadNode->Next;//新节点与前后节点连接
HeadNode->Next = NewNode;//注意!!此功能在插入函数(InsertNode)中实现
}
void deletestudent() {//删除节点
char name[10];
printf("请输入需要删除的学生名字\n");
scanf("%s", name);
deletenode(StudentNode, name);
}
void deletenode(struct Node* headnode, char *name) {//将头节点(表头),和名字(查找)输入函数
struct Node* posnode = headnode->Next;
struct Node* posnodefront = headnode;//初始化目标节点的位置
if (posnode == NULL) {
printf("数据为空,无法删除");
}
else
{
while (strcmp(posnode->data.name, name)) {//判断名字是否相等
posnodefront = posnode;
posnode = posnodefront->Next;//相当于pmove,遍历链表
if (posnode == NULL) { printf("未找到指定位置,无法删除"); return; }
}
posnodefront->Next = posnode->Next;//连接节点
free(posnode);
}
}
struct Node* SearchNode(struct Node* StudentNode, char* name) {//查找学号节点
struct Node* pMove = StudentNode->Next;
if (pMove == NULL) {
printf("未找到该学生");
return(pMove);
}
else
{
while (strcmp(pMove->data.number, name)) {
pMove = pMove->Next;
if (pMove == NULL)break;
}
return pMove;
}
}
void PrintList(struct Node* StudentNode) {//打印单个节点
printf("姓名\t性别\t学号\t科目成绩\n");
printf("%s\t%s\t%s\t%f\t%f\t%f\n", StudentNode->data.name, StudentNode->data.sex, StudentNode->data.number, StudentNode->data.grade1, StudentNode->data.grade2, StudentNode->data.grade3);
}
void PrintNode(struct Node* StudentNode) {//浏览信息
struct Node* pow = StudentNode->Next;
printf("姓名\t性别\t学号\t科目成绩\n");
while (pow) {
printf("%s\t%s\t%s\t%f\t%f\t%f\n", pow->data.name, pow->data.sex, pow->data.number, pow->data.grade1, pow->data.grade2, pow->data.grade3);
pow = pow->Next;
}
}
void SaveFile1(char* filename, struct Node* StudentNode) {
FILE* fp = fopen(filename, "w");
struct Node* pow = StudentNode->Next;
while (pow) {//当指针非空时
fprintf(fp, "%s\t%s\t%s\t%f\t%f\t%f\n", pow->data.name, pow->data.sex, pow->data.number, pow->data.grade1, pow->data.grade2, pow->data.grade3);//文件写入,同时数据之间存在间隙
pow = pow->Next;//遍历链表
}
fclose(fp);
}
void ReadFromFile(char *filename, struct Node* StudentNode) {//加载之前的文件
FILE* fp = fopen(filename, "r");
if (fp == NULL) {
fp = fopen(filename, "w");
}
struct Student data;
while (fscanf(fp, "%s\t%s\t%s\t%f\t%f\t%f\n", data.name, data.sex,
data.number, &data.grade1, &data.grade2, &data.grade3) != -1) {//这样写会有bug,因为一旦有数据格式非法输入就会导致数据栈损坏
CreatNodeList(StudentNode, data);//导入之前生成的链表
memset(&data, 0, sizeof(data));//内存初始化
}
fclose(fp);
}
void printBubblesort(struct Node* StudentNode) { //传入头结点进行冒从小到大的泡算法,然后打印
struct Student p[1000];
struct Node* pow = StudentNode->Next;
int n = 0;
while (pow) {//当结构体指针非空时
p[n] = pow->data;//这里之前会报错,不知道为什么?
pow = pow->Next;//遍历链表
n++;
}
int i, j;
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (p[i].grade1 + p[i].grade2 + p[i].grade3 >= p[j].grade1 + p[j].grade2 + p[j].grade3) {//判断的条件,顺序为从小到大
struct Student temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
printf("排名\t姓名\t性别\t学号\t科目1成绩\t科目2成绩\t科目3成绩\t科目总分\n");
for (i = 0; i < n; i++) {
printf("[ %d ]\t%s\t%s\t%s\t%f\t%f\t%f\t%f\n", i + 1, p[i].name, p[i].sex, p[i].number, p[i].grade1, p[i].grade2, p[i].grade3, p[i].grade1+p[i].grade2+p[i].grade3);
}
}
void PrintAverage(struct Node* StudentNode) {//打印平均成绩
struct Node* pow = StudentNode->Next;
while (pow) {
float aver = (pow->data.grade1 + pow->data.grade2 + pow->data.grade3) / 3;//定义并计算平均数
printf("%s\t%s\t%s\t%f\n", pow->data.name, pow->data.sex, pow->data.number, aver);
pow = pow->Next;
}
}
void PrintAverage80(struct Node* StudentNode) {//打印平均成绩大于80分
struct Node* pow = StudentNode->Next;
while (pow) {
float aver = (pow->data.grade1 + pow->data.grade2 + pow->data.grade3) / 3;//定义并计算平均数
if (aver > 80) {
printf("%s\t%s\t%s\t%f\n", pow->data.name, pow->data.sex, pow->data.number, aver);
}
pow = pow->Next;
}
}
struct Node* SearchNode2(struct Node* StudentNode, char* name) {//查找姓名节点
struct Node* pMove = StudentNode->Next;
if (pMove == NULL) {
printf("未找到该学生");
return(pMove);
}
else
{
while (strcmp(pMove->data.name, name)) {
pMove = pMove->Next;
if (pMove == NULL)break;
}
return pMove;
}
}
void printBubblesort2(struct Node* StudentNode) { //传入头结点进行冒从大到小的泡算法,然后打印
struct Student p[1000];
struct Node* pow = StudentNode->Next;
int n = 0;
while (pow) {//当结构体指针非空时
p[n] = pow->data;//这里为什么会报错?
pow = pow->Next;//遍历链表
n++;
}
int i, j;
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (p[i].grade1 + p[i].grade2 + p[i].grade3 <= p[j].grade1 + p[j].grade2 + p[j].grade3) {//判断的条件,顺序为从小到大
struct Student temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
printf("排名\t姓名\t性别\t学号\t科目1成绩\t科目2成绩\t科目3成绩\t科目总分\n");
for (i = 0; i < n; i++) {
printf("[ %d ]\t%s\t%s\t%s\t%f\t%f\t%f\t%f\n", i + 1, p[i].name, p[i].sex, p[i].number, p[i].grade1, p[i].grade2, p[i].grade3, p[i].grade1 + p[i].grade2 + p[i].grade3);
}
}
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void AppearCursor()
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 1 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void Windowstime()
{
SYSTEMTIME sys;
printf("\t\t\t\t\t 当前时间为:");
GetLocalTime(&sys); //获取系统时间到程序的函数
printf("%4d-%02d-%02d %02d:%02d \n\n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute); //按照年/月/日 时/分 格式打印
return;
}
void cursor(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void welcome() {//欢迎函数
HideCursor(); //为了美观 隐藏光标
cursor(0, 21); //将光标定位在(0,21)处
Windowstime(); //显示系统时间
int i, j;
char star = '*';
for (i = 0; i <= 100; i++) {
cursor(44, 8);
printf("欢迎使用学生信息管理系统");
cursor(53, 12);
printf("启动中...");
cursor(28, 16);
printf("<");
for (j = 0; j < 50; j++) { //打印进度条
if (j < i / 2)
printf("*");
else printf("o");
}
printf(">");
printf("%d%%", i);
Sleep(20); //每 20ms 进一格
}
return;
}
void PrintExit() {//关闭界面
system("cls");
HideCursor();
cursor(0, 21);
Windowstime();
int i, j;
for (i = 0; i <= 100; i++) {
cursor(44, 8);
printf("感谢使用学生信息管理系统");
cursor(49, 12);
printf("数据保存中...");
cursor(28, 16);
printf("<");
for (j = 0; j < 50; j++) {
if (j < i / 2)
printf("*");
else printf("o");
}
printf(">");
printf("%d%%", i);
Sleep(5);
}
cursor(0, 26);
return;
}