/* C语言小项目——学生管理系统
学习目标:
1. C语言知识点汇总与梳理
2. 编程思路的锻炼
功能分析:
需要实现哪些功能
录入学生的功能
按照....去查询
对信息修正
对信息进行删除
排序 按照成绩倒序输出
导入和导出 文件操作
排序
登录--->登录界面
数据如何管理?
学生管理系统 --->多个学生的信息
顺序表 尾端能够快速插入(中间插入和删除不方便)
连续存储 连续内存(申请不便)
链表 在任意地方插入删除都很简单
查找不便(从头到尾查找)
栈 和队列
链表--->单链表 双链表
带一个头 函数比较好写
结构体 指针 文件操作 函数 传参 数组 循环
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<Windows.h>
typedef struct student
{
char name[20];
int age;
float grade;
int ID;
//.....
struct student* pre;
struct student* next;
}STU;
void load()
{
char admin[20];
char passWord[20];
while (1)
{
printf("请输入你的账户\n");
gets(admin);
printf("请输入你的账户\n");
gets(passWord);
if (strcmp(admin, "summer") == 0 && strcmp(passWord, "123") == 0)
{
printf("账户和密码正确\n");
break;//输入正确 退出循环
}
else
{
printf("账户和密码不正确,请重新输入\n");
}
}
/*
如果有涉及到多个账号 选择文件保存
每次从文件中读取数据进行验证 验证 成功--->退出循环
*/
}
#if 0//二进制操作
void saveFile(STU*head)//保存所有的学生信息
{
FILE *fp = fopen("student.txt", "wb");//准备文件
//二进制方式 fwrite
//文本文件的方式 fprintf
STU*p = head->next;
while (p!= head)
{
//读取里面的数据
fwrite(p, sizeof(STU), 1, fp);//写入数据
p = p->next;
}
fclose(fp);
printf("写入成功\n");
}
void readFile(STU*head)
{
STU* p;
FILE* fp = fopen("student.txt", "rb");
if (fp == NULL) return;
while (1)
{
p= (STU*)malloc(sizeof(STU));//先准备一个结构体
fread(p, sizeof(STU), 1, fp);//读取内容
if (feof(fp))
{
//已经读取完毕 不需要插入
free(p);//直接释放节点
break;//直接结束读取
}
//插入到链表当中(头插)
p->next = head->next;
p->pre = head;
p->pre->next = p;
p->next->pre = p;
//准备下一次读取
}
fclose(fp);
}
#else//文本文件的操作
void saveFile(STU*head)//保存所有的学生信息
{
FILE *fp = fopen("student.txt", "w");//准备文件
//二进制方式 fwrite
//文本文件的方式 fprintf
STU*p = head->next;
while (p != head)
{
//读取里面的数据
//fwrite(p, sizeof(STU), 1, fp);//写入数据
fprintf(fp, "%s\t%d\t%.1f\t%d\n", p->name, p->age, p->grade, p->ID);
p = p->next;
}
fclose(fp);
printf("写入成功\n");
}
void readFile(STU*head)
{
STU* p;
FILE* fp = fopen("student.txt", "r");
if (fp == NULL) return;
while (1)
{
p = (STU*)malloc(sizeof(STU));//先准备一个结构体
//fread(p, sizeof(STU), 1, fp);//读取内容
//%s读取字符串 用空格或者\t或者换行隔开都可以
//不适合读取有空格的字符串
if(fscanf(fp, "%s\t%d\t%f\t%d\n", p->name, &p->age, &p->grade, &p->ID)==EOF)
{
//已经读取完毕 不需要插入
free(p);//直接释放节点
break;//直接结束读取
}
//插入到链表当中(头插)
p->next = head->next;
p->pre = head;
p->pre->next = p;
p->next->pre = p;
//准备下一次读取
}
fclose(fp);
}
#endif
void freeNode(STU*head)//删除整个链表
{
STU *p, *q;
p = head->next;
while (p != head)
{
q = p;
p = p->next;
free(q);
}
free(head);
}
void insertStu(STU*head)
{
STU*p = (STU*)malloc(sizeof(STU));
printf("请输入你要录入的名字\n");
scanf("%s", p->name);
printf("请输入你要录入的年龄\n");
scanf("%d", &p->age);
printf("请输入你要录入的成绩\n");
scanf("%f", &p->grade);
printf("请输入你要录入的学号\n");
scanf("%d", &p->ID);
//scanf_s("%s", p->name, 20);
//插入链表当中 (尾插)
p->next = head;
p->pre = head->pre;
p->pre->next = p;
p->next->pre = p;
}
void searchByName(STU *head)
{
char name[20];
printf("请输入你要查找的名字\n");
//strcmp 张三丰 输入 张三
//strstr 判断是否是子字符串
scanf("%s", name);
STU *p = head->next;
while (p != head)
{
//if (strcmp(p->name, name) == 0)
if (strstr(p->name,name))//没找到返回NULL
{
printf("名字:%s\t 年龄%d\t 分数%.1f\t学号%d\n", p->name, p->age, p->grade, p->ID);
}
p = p->next;
}
}
void changeStu(STU*head)//按照分数 修改信息
{
//先找出所有可能的选项 然后列举出来
//如果保存多个节点的首地址? 顺序表的方式来保存
STU* arr[100];//指针数组 用来存放节点的首地址
int len = 0;//存放的数据个数
float a, b,c;
int num;
printf("请输入你要查找的分数的范围 {a,b}");
scanf("%f %f", &a, &b);
if (a > b)//让a<b
{
c = a;
a = b;
b = c;
}
STU*p = head->next;
while (p != head)
{
if (p->grade >= a&&p->grade <= b)//找到一个学生
{
if (len >= 100)
{
//先不进行插入 一页满了
//先让用户看一下 有没有要修改的内容 有--->修改
//没有 这个表格清空
for (int i = 0; i < len; ++i)
{
printf("编号%d 名字:%s\t 年龄%d\t 分数%.1f\t学号%d\n",i+1,arr[i]->name, arr[i]->age, arr[i]->grade, arr[i]->ID);
}
printf("请选择你要修改的学生的编号");
scanf("%d", &num);
if (num <= len&&num>0)
{
printf("请输入你要录入的名字\n");
scanf("%s", arr[num-1]->name);
printf("请输入你要录入的年龄\n");
scanf("%d", &arr[num-1]->age);
printf("请输入你要录入的成绩\n");
scanf("%f", &arr[num-1]->grade);
printf("请输入你要录入的学号\n");
scanf("%d", &arr[num-1]->ID);
}
len = 0;//清空这个表
}
else
{
arr[len++] = p;//结点的位置插入到顺序表当中
}
}
p = p->next;
}
if (len!=0)
{
//先不进行插入 一页满了
//先让用户看一下 有没有要修改的内容 有--->修改
//没有 这个表格清空
for (int i = 0; i < len; ++i)
{
printf("编号%d 名字:%s\t 年龄%d\t 分数%.1f\t学号%d\n", i + 1, arr[i]->name, arr[i]->age, arr[i]->grade, arr[i]->ID);
}
printf("请选择你要修改的学生的编号");
scanf("%d", &num);
if (num <= len&&num>0)
{
printf("请输入你要录入的名字\n");
scanf("%s", arr[num - 1]->name);
printf("请输入你要录入的年龄\n");
scanf("%d", &arr[num - 1]->age);
printf("请输入你要录入的成绩\n");
scanf("%f", &arr[num - 1]->grade);
printf("请输入你要录入的学号\n");
scanf("%d", &arr[num - 1]->ID);
}
len = 0;//清空这个表
}
}
void deletStu(STU*head)
{
//按照什么方式去删除一个信息
//按照 学号 满足这个范围之内的 删除
int x, y,z;
printf("请输入你要删除的ID的范围");
scanf("%d %d", &x, &y);
if (x > y)
{
z = x;
x = y;
y = z;
}
STU*p = head->next,*q;
while (p != head)
{
if (p->ID >= x&&p->ID <= y)
{
//找到了直接删除
q = p;//q保留要删除的结点
p = p->next;
q->next->pre = q->pre;
q->pre->next = q->next;
free(q);
}
else
{
p = p->next;
}
}
}
void printAll(STU*head)
{
STU*p = head->next;
printf("学生的信息:\n");
while (p != head)
{
printf("名字:%s\t 年龄%d\t 分数%.1f\t学号%d\n", p->name, p->age, p->grade, p->ID);
p = p->next;
}
printf("-----------------------------------");
Sleep(2000);
}
void swap(STU*a, STU*b)//用结构体指针交换两个结构体
{
STU temp;//中间变量
//数据域和指针域
//指针域不动
temp = *a;
a->age = b->age;
a->ID = b->ID;
a->grade = b->grade;
strcpy(a->name, b->name);
b->age = temp.age;
b->ID =temp.ID;
b->grade = temp.grade;
strcpy(b->name, temp.name);
}
void sort(STU *head)
{
//按照学号排序 选择 交换
STU*p, *q,*temp;
for (p = head->next; p != head; p = p->next)//从头到尾
{
//找到最小的学号
temp = p;
for (q = p->next; q != head; q = q->next)
{
if (temp->ID > q->ID)
{
temp = q;//每次保留更小的结点位置
}
}
swap(temp, p);//交换两个位置的结点
}
}
void menu()//菜单
{
int choice;//用户的选择
STU* head = (STU*)malloc(sizeof(STU));
head->next = head->pre = head;//初始化操作
//循环双链表 作为存放数据的链表
readFile(head);//进入菜单之前 读取文件内容
while (1)//循环
{
system("cls");//清屏函数
printf("欢迎进入学生管理系统\n");
printf("请输入你要使用的功能\n");
printf("1.录入信息\n");
printf("2.查询信息\n");
printf("3.修改信息\n");
printf("4.删除信息\n");
printf("5.打印信息\n");
printf("6.排序\n");
printf("0.退出菜单\n");
scanf("%d", &choice);
switch (choice)
{
case 0://退出
saveFile(head);//对于信息 是否需要保存?
freeNode(head);//释放内存
return;//退出这个函数 堆内存需要释放
break;
case 1://录入
insertStu(head);//录入学生信息
break;
case 2://查询
while (choice)
{
system("cls");//清屏函数
printf("开始查询 选择你要的查询方式\n");
printf("1.按照名字查询\n");
//....
printf("0.退出\n");
scanf("%d", &choice);
switch (choice)
{
case 1:
searchByName(head);
break;
case 0://退出
break;
default:
break;
}
}
break;
case 3://修改
changeStu(head);
break;
case 4://删除
deletStu(head);
break;
case 5://全部打印
printAll(head);
break;
case 6://排序
//根据年龄?成绩?名字?学号?
//strcmp >0
//英文字典
//abc < bac
sort(head);
break;
default:
break;
}
}
}
int main()
{
menu(); //主菜单
getchar();
return 0;
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!