拥有基本的学生信息系统的功能, 功能点如下所示:
1.添加学生信息
2.修改学生信息
3.删除学生信息
4.查看学生信息
5.搜索学生信息
6.查看系统学生总人数
7.学生信息排序
8.保存学生信息(保存在D:/students.txt)
9.导入学生信息(导入D:/students.txt文件中的信息)
主界面
1.添加学生信息
2.修改学生信息
3.删除学生信息
4.查看学生信息
5.搜索学生信息
6.查看系统学生总人数
7.学生信息排序
8.保存学生信息(保存在D:/students.txt)
9.导入学生信息(导入D:/students.txt文件中的信息)
学生信息管理系统代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#include<windows.h>
struct Student {
int id; //学号
char name[20]; //名字
int sex; //性别 0为女,1为男
char specialized[25]; //学生的专业
char date[25]; //出生日期
char address[255]; //学生住址
float score; //学生分数
//Stu -> Stu -> Stu -> Stu -> NULL
struct Student *next; //链表的构成,指向下一个结构体
/*struct student *next 是
申请了一个 struct student
这结构体类型的指针
*/
};
//学生管理系统中的总人数数量
int total_count = 0;
//重定义 struct Student 为 Stu(起别名) ,后续可以直接使用Stu代替 struct Student
typedef struct Student Stu;
//主菜单
void mainMenu()
{
printf(" 0.退出\n");
printf(" 1.新增学生信息\n");
printf(" 2.修改学生信息\n");
printf(" 3.删除学生信息\n");
printf(" 4.查看学生信息\n");
printf(" 5.学生信息搜索\n");
printf(" 6.学生人数统计\n");
printf(" 7.按英语成绩排序\n");
printf(" 8.学生信息保存\n");
printf(" 9.导入学生信息\n");
printf(" ******请选择:");
}
//退出程序
void exitProgram()
{
system("cls");
system ("color 04");
int i, j, k, l, m;
char c=3; //ASCII码里面 3 就是一个字符小爱心
for (i=1; i<=5; i++) printf("\n"); //开头空出5行
for (i=1; i<=3; i++)
{ //前3行中间有空隙分开来写
for (j=1; j<=32-2*i; j++) printf(" "); //左边的空格,每下一行左边的空格比上一行少2个 //8*n-2*i
for (k=1; k<=4*i+1; k++) printf("%c", c);//输出左半部分字符小爱心
for (l=1; l<=13-4*i; l++) printf(" "); //中间的空格,每下一行的空格比上一行少4个
for (m=1; m<=4*i+1; m++) printf("%c", c);//输出右半部分字符小爱心
printf("\n"); //每一行输出完毕换行
}
for (i=1; i<=3; i++)
{ //下3行中间没有空格
for (j=1; j<=24+1; j++) printf(" "); //左边的空格 //8*(n-1)+1
for (k=1; k<=27; k++)
if (k==8)
printf("谢");
else if (k==10)
printf("谢");
else if (k==12)
printf("使");
else if (k==14)
printf("用");
else
printf("%c", c);//输出字符小爱心
printf("\n"); //每一行输出完毕换行
}
for (i=7; i>=1; i--)
{ //下7行
for (j=1; j<=40-2*i; j++) printf(" "); //左边的空格,每下一行左边的空格比上一行少2个//8*(n+1)-2*i
for (k=1; k<=4*i-1; k++) printf("%c", c);//每下一行的字符小爱心比上一行少4个(这个循环是i--)
printf("\n"); //每一行输出完毕换行
}
for (i=1; i<=39; i++)printf(" "); //最后一行左边的空格
printf("%c\n", c); //最后一个字符小爱心
for (i=1; i<=5; i++)printf("\n"); //最后空出5行
}
//添加学生
void addStudent(Stu *head)
{
//清空屏幕
system("cls");
//找到最后一个节点,然后才能添加
//最后一个节点的 next 为 NULL
//Stu->Stu->Stu->NULL
while(head != NULL && head->next!=NULL)//遍历,很重要,是结点,连接着接下来输入的数据与上一个数据。
{
head = head->next;//head->next==NULL;找到存放指针为空的结构体,找到尾结点。
}
printf("请输入学生个数: ");
int num;
scanf("%d",&num);
int i=1;
for(; i<= num; i++){
printf("请输入第%d个学生信息\n",i);
Stu *stu;//开辟一个单独结构体,字母任意。
stu=(Stu *)malloc(sizeof(Stu));//开辟内存
/*
malloc函数只是开辟一块区域/
//calloc函数与malloc 函数的区别仅在于一次可以分配n块区域。
用变量表示长度,想对数组的大小作动态说明,这是错误的。
但是在实际的编程中,往往会发生这种情况,
即所需的内存空间取决于实际输入的数据,而无法预先确定。
对于这种问题,用数组的办法很难解决。为了解决上述问题,
C语言提供了一些内存管理函数,
这些内存管理函数可以按需要动态地分配内存空间,
也可把不再使用的空间回收待用,
为有效地利用内存资源提供了手段。
*/
printf("学号:");
scanf("%d",&stu->id);
printf("学生姓名: ");
scanf("%s",stu->name);
printf("性别:");
scanf("%d",&stu->sex);
printf("专业:");
scanf("%s",stu->specialized);
printf("出生日期:");
scanf("%s",stu->date);
printf("家庭住址:");
scanf("%s",stu->address);
printf("总成绩:");
scanf("%f",&stu->score);
stu->next=NULL;//结构体的存地址的地方初始化 //结构体初始化。。
head->next=stu;//连接链表
//head指向最后一个节点,刚刚给stu添加到节点后面了,所以限制stu就是最后一个节点
//我们让head指向stu,此时head依旧指向最后一个节点上了
head=stu;
system("cls");
}
total_count += num; //+= --> total_count = total_count + num;
printf("信息录入成功!!!\n");
system("pause");
system("cls");
/*
system("pause")作用:
让操作系统来暂停该程序进程的执行,
同时程序运行到此语句处时,
会在程序的窗口上显示“Press any key to continue . . .”
也就是 “按任意键继续...”,
即等待用户按下任意一个按键使该程序从暂停状态
返回到执行状态继续从刚才暂停的地方开始执行。
*/
/*system("cls")就是执行命令“清屏”的意思。*/
}
//打印所有学生信息
void printAllStudents(Stu *q)
{
system("cls");
while(q->next!=NULL)
{
q=q->next;/// 数据从第二个开始存,应该从第二个进行查找。
printf("学号:%d\n",q->id);
printf("姓名:%s\n",q->name);
printf("性别:%s\n",q->sex == 0 ? "女" : "男");
printf("专业:%s\n",q->specialized);
printf("出生日期:%s\n",q->date);
printf("家庭地址:%s\n",q->address);
printf("总成绩:%.2f\n",q->score);
printf("\n");
}
system("pause");
system("cls");
return;
}
//删除学生信息
void deleteStudent(Stu *head)
{
system("cls");
Stu *prev = head; //用于删除节点,记录上一个节点
head = head->next;//存数据从第二个开始存,应该从第二个进行查找。
printf("请输入删除的人的姓名:");
char name[20];
scanf("%s",name);
//用于判断是否找到输入名字的学生
int num = 0;
//一直找到head为NULL,匹配了就删除退出循环
while(head != NULL)
{
//存数据从第二个开始存,应该从第二个进行查找。
if(strcmp(head->name,name)==0){
num = 1;
//匹配到name相同的节点
//删除head节点
//删除前: prev->head->xxx->xxx->NULL;
//删除后: prev->xxx->xxx->NULL;
//将指向删除的地址和后一个地址连接,跳过删除对象。
prev->next=head->next;
free(head); //清空内存
head = NULL; //置为空,防止后续被调用
/*
清空数据,结构体空间还在。
free后只是做了个标记,告诉系统这块内存不用了,
一旦调用后, 那个地址是不被保护的,
也就是说其他的变量随时可能占用那个地址。*/
break;
}
prev = prev->next;
head = head->next;
}
if(num != 1)
{
printf("删除失败\n");
}
else
{
printf("删除成功\n");
total_count -= 1;
}
}
//搜索学生信息
void searchStudent(Stu *q)
{
system("cls");
printf("请输入查找人姓名:");
char name[20];
scanf("%s",name);
int num = 0;
//第二个开始存储的学生信息,从第二个节点开始查找
q=q->next;
while(q!=NULL){
if(strcmp(q->name,name)==0){
num = 1;
system("cls");//清空屏幕
printf("\n\n查找完成\n\n");
printf("学号:%d\n",q->id);
printf("姓名:%s\n",q->name);
printf("性别:%s\n",q->sex == 0 ? "女" : "男");
printf("专业:%s\n",q->specialized);
printf("出生日期:%s\n",q->date);
printf("家庭地址:%s\n",q->address);
printf("总成绩:%.2f\n",q->score);
}
q=q->next;
}
if(num == 0)
{
printf("\n\n查无此人\n\n");
}
system("pause");
system("cls");
}
//交换两个节点的信息
void swapStudent(Stu *prev,Stu *head)
{
int t1;
t1=prev->id;
prev->id=head->id;
head->id=t1;
char t2[20];
strcpy(t2,prev->name);
strcpy(prev->name,head->name);
strcpy(head->name,t2);
int t3;
t3 = prev->sex;
prev->sex = head->sex;
head->sex = t3;
char t4[20];
strcpy(t4,prev->specialized);
strcpy(prev->specialized,head->specialized);
strcpy(head->specialized,t4);
char t5[20];
strcpy(t5,prev->date);
strcpy(prev->date,head->date);
strcpy(head->date,t5);
char t6[20];
strcpy(t6,prev->address);
strcpy(prev->address,head->address);
strcpy(head->address,t6);
float t7;
t7=prev->score;
prev->score = head->score;
head->score=t7;
}
//学生排序,按照分数从大到小排序
void sortStudents(Stu *head)
{
//系统中人数小于2就无需排序
if(total_count<2)
{
printf("\n\n数据过少,不进行排序!\n\n");
system("pause");
system("cls");
return;
}
system("cls");
printf("请输入成绩排序规则:\n");
printf("输入0按照成绩从小到大排序\n");
printf("输入1按照成绩从大到小排序\n");
int op;
scanf("%d",&op);
head = head->next;//head指向的是链表的第三个节点,第二个有效节点
Stu *pFirst = NULL, *pSecond = NULL, *pEnd = NULL;
pFirst = head;
pSecond = head;
while(pFirst != pEnd)
{
while(pFirst->next != pEnd)
{
if(op == 0)
{
//从小到大排序
if(pFirst->score > pFirst->next->score)
{
//交换两个节点的信息
swapStudent(pFirst,pFirst->next);
}
}
else
{
//从大到小排序
if(pFirst->score < pFirst->next->score)
{
//交换两个节点的信息
swapStudent(pFirst,pFirst->next);
}
}
pFirst = pFirst->next;
}
//此时pFirst是链表中的最后一个节点了
pEnd = pFirst;
pFirst = head;
}
printf("\n\n排序成功!!!\n\n");
system("pause");
system("cls");
}
//修改学生信息
void updateStudent(Stu *head)
{
system("cls");
//从第二个节点开始查找
Stu *q=head->next;
printf("请输入修改人姓名:");
char name[20];
scanf("%s",name);
while(q != NULL){
if(strcmp(q->name,name)==0)
{
printf("\n\n存在该学生信息!\n\n");
printf("请输入要修改的学生学号:");
scanf("%d",&q->id);
printf("请输入要修改的学生姓名:");
scanf("%s",q->name);
printf("请输入要修改的学生性别:");
scanf("%d",&q->sex);
printf("请输入要修改的学生专业:");
scanf("%s",q->specialized);
printf("请输入要修改的学生出生日期:");
scanf("%s",q->date);
printf("请输入要修改的学生家庭地址:");
scanf("%s",q->address);
printf("请输入要修改的学生的总成绩:");
scanf("%f",&q->score);
printf("\n\n修改成功!!!\n\n");
break;
}
q=q->next;
}
if(q==NULL)
{
printf("\n\n不存在该学生信息\n\n\n");
}
}
//保存所有学生信息
void saveStudents(Stu *q)
{
system("cls");
FILE * fp = fopen("D:\\students.txt", "a");
if(fp == NULL)
{
printf("打开文件失败!!!\n\n");
return;
}
while(q->next!=NULL)
{
q=q->next;
fprintf(fp, "%d %s %d %s %s %s %f\n",q->id,q->name,q->sex,q->specialized,q->date,q->address,q->score);
/*fprintf函数作用:传送格式化输出到一个文件中
*/
}
fclose(fp);
printf("\n\n文件保存成功!!!\n\n\n");
}
//导入学生信息到链表的最后
void importStudents(Stu *head)
{
system("cls");
FILE *fp=fopen("D:\\students.txt","r");
if(fp==NULL)
{
printf("打开文件失败\n");
return;
}
while(head->next!=NULL)
{
head = head->next;
}
int num = 0;
char buf[1024];
while (fgets(buf, sizeof(buf), fp) != NULL)
{
Stu *q=(Stu*)malloc(sizeof(Stu));
q->next=NULL;
printf("%s", buf);
//格式化输入
sscanf(buf, "%d %s %d %s %s %s %f\n",&q->id,q->name,&q->sex,q->specialized,q->date,q->address,&q->score);
head->next=q;
head = q;
num++;
}
fclose(fp);
if(num != 1)
{
total_count += num;
printf("导入成功\n");
}
else
{
printf("无数据");
}
}
int main()
{
//开辟一个空的头节点
Stu *head;
head=(Stu *)malloc(sizeof(Stu));
head->next=NULL;
system("cls"); //清空控制台
system("color 06"); //控制台设置颜色
//进来之后死循环,展示菜单,等待用户输入
while(1)
{
mainMenu();
int op;
scanf("%d",&op);
switch(op)
{
case 0:
{
//退出程序
exitProgram();
printf("\n\n\n 谢谢使用【手动微笑】\n\n");
return 0;
}
case 1:
{
//添加学生信息
addStudent(head);
break;
}
case 2:
{
//修改学生信息
updateStudent(head);
system("pause");
system("cls");
break;
}
case 3:
{
//删除学生信息
deleteStudent(head);
system("pause");
system("cls");
break;
}
case 4:
{
//打印所有学生信息
printAllStudents(head);
break;
}
case 5:
{
//搜索学生信息
searchStudent(head);
break;
}
case 6:
{
printf("\n\n总人数为:%d\n\n\n",total_count);
system("pause");
system("cls");
break;
}
case 7:
{
//学生排序,按照分数从大到小排序
sortStudents(head);
break;
}
case 8:
{
//保存所有学生信息
saveStudents(head);
system("pause");
system("cls");
break;
}
case 9:
{
//导入学生信息到链表的最后
importStudents(head);
system("pause");
system("cls");
break;
}
default:
{
printf("\n\n您的输入有误!!!请重新输入\n");
system("pause");
system("cls");
break;
}
}
}
}