学生信息管理
(1)问题描述
学生信息包括:学号,姓名,年龄,性别,出生年月,地址,电话,E-mail等。试设计一学生信息管理系统,使之能提供以下功能:
- 系统以菜单方式工作
- 学生信息录入功能(学生信息用文件保存)---输入
- 学生信息浏览功能——输出
- 查询、排序功能——算法
1、按学号查询
2、按姓名查询
- 学生信息的删除与修改(可选项)
(2)功能要求
- 界面简单明了;
- 有一定的容错能力,比如输入的成绩不在0~100之间,就提示不合法,要求重新输入;
- 最好用链表的方式实现。
(3)算法分析
首先,一个学生包括这么多的属性,应该考虑定义一个结构,其次,我们应该考虑数据的存储形式:是定义一个数组来存储,还是定义一个链表呢?在这里假如我们以数组的方式来存储,当然可以,但是我们知道,假如我们定义一个数组的话,我们首先必须知道学生人数大概是多少,以便我们确定数组的大小,但是题目中没有给出,而且题目要求中有大量的删除、插入操作,所以用链表的方式比较方便。
效果展示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
typedef struct Student //学生信息包括:学号,姓名,年龄,性别,出生年月,地址,电话,E-mail。
{
int number;
char name[20];
int age;
char sex[6];
char birthday[12];
char address[20];
char phone[12];
char email[20];
struct Student *next;
} Student;
void menu();//函数声明
Student *Read();
void Write(Student *head);
void Scan(Student *current);
Student *Sort(Student *head);
Student *Input();
Student *Delete(Student *head);
Student *Add(Student *head);
void Show(Student *head);
Student *Find(Student *head);
Student *Find(Student *head);
Student *Change(Student *headI);
Student *Read()//从文件读出链表的函数
{
Student *head=NULL,*pre=NULL,*current=NULL;
FILE *fp;
if(!(fp=fopen("date.txt","rb"))) //打开文件
{
printf("此文件不可打开!");
system("pause");
return head;
}
char ch=fgetc(fp);
rewind(fp);//此处很重要,如果丢失了就会出错 ,因为上一条语句后fp不是指向文件开头了
if(ch!=EOF) //判断:判断文件是否为空,解决文件为空的情况
{
head=pre=current=(Student *)malloc(sizeof(Student));//创建链表
fread(current,sizeof(Student),1,fp);
while(current->next)
{
pre=current;
current=(Student *)malloc(sizeof(Student));
pre->next=current;
fread(current,sizeof(Student),1,fp);
}
}
else
{
printf("此文件为空,请先输入数据");//提示
system("pause");
}
fclose(fp);//关闭文件
menu();//刷新界面
return head;
}
void Write(Student *head) //写入数据函数:把数据写入到磁盘中
{
FILE *fp;
if(!(fp=fopen("date.txt","wb"))) //打开并准备重写文件
{
printf("此文件不可打开!");
system("pause");
return;
}
while(head) //写入数据
{
fwrite(head,sizeof(Student),1,fp);
head=head->next;
}
fclose(fp);
}
void Scan(Student *current)//输入数据,在其他地方可调用
{
printf("姓名: ");//name
scanf("%s",¤t->name);
printf("年龄: ");//age
scanf("%d",¤t->age);
while((current->age > 120)||(current->age < 0))//判断是否为合法输入
{
printf("输入错误,重新输入年龄:");
scanf("%d",¤t->age);
}
printf("性别: ");//sex
scanf("%s",¤t->sex);
printf("生日: ");//birthday
scanf("%s",¤t->birthday);
printf("地址: ");//address
scanf("%s",¤t->address);
printf("电话: ");//phone
scanf("%s",¤t->phone);
printf("邮箱: ");//email
scanf("%s",¤t->email);
}
Student *Input()//信息录入与保存函数
{
puts("输入学号为0结束");//学号输0表示结束
Student *head=NULL,*pre=NULL,*current=NULL;
head=pre=current=(Student *)malloc(sizeof(Student));
printf("学号: ");
scanf("%d",¤t->number);
if(current->number) Scan(current);
else head=NULL;
while(current->number)
{
pre=current;
current=(Student *)malloc(sizeof(Student));
printf("学号: ");
scanf("%d",¤t->number);
if(!current->number)
{
printf("---输入完成---");
system("pause");
break;
}
Scan(current);
pre->next=current;
}
pre->next=NULL;
head=Sort(head);//排序
Write(head);//重写
return head;
}
Student *Sort(Student *head)//排序函数
{
if(head) //判断
{
Student *pre,*current,*next;
pre=current=head;
next=head->next;
int count=0;
while(head) //计算一共有多少条数据
{
head=head->next;
count++;
}
head=current;//头返回起点
int i,j,flag;
for(i=count-1; i>0; i--) //冒泡排序法实现
{
flag=1;
for(j=0; j<i; j++)
{
if(current->number>next->number)
{
current->next=next->next;
next->next=current;
if(j) //不是首节点
pre->next=next;
else
head=next;
}
current=current->next;
next=next->next;
if(j)
pre=pre->next;
flag=0;
}
pre=current=head;
next=head->next;
if(flag)
break;
}
}
else
{
printf("此文件为空,请先输入数据");//提示
system("pause");
}
return head;
}
Student *Delete(Student *head)//删除数据
{
if(head) //判断 ,当文件夹为空(链表为空的时候)
{
int num,j=1;
puts("请输入您想要删除的学生的学号");
scanf("%d",&num);
Student *pre=head,*current=head;
int count=1;
while(current->number!=num) //寻找要删除的数据
{
count++;
pre=current;
current=current->next;
if(!current)
{
j=0;
break;
}
}
if(j) //准备删除
{
if(count==1)
{
head=head->next;
free(pre);
}
else
{
pre->next=current->next;
free(current);
}
Write(head);
printf("\n");
printf("---删除成功!---\n");
printf("\n");
printf(">>>现在的学生信息为:\n");
Show(head);
}
else
{
printf("不存在此人!");
system("pause");
}
}
else
{
printf("此文件为空,请先输入数据");//空文件
system("pause");
}
return head;
}
Student *Add(Student *head)//添加数据:按排序插入
{
Student *pre=head,*current=head;
Student *p=(Student*)malloc(sizeof(Student));
printf("学号:");
scanf("%d",&p->number);
Scan(p);
if(head) //判断,防止文件夹为空
{
if( p->number <= head->number )
{
p->next=head;
head=p;
}
else
{
current=current->next;
while(current)
{
if( p->number <= current->number )
{
pre->next=p;
p->next=current;
break;
}
else
{
pre=current;
current=current->next;
}
}
if(!current)
{
pre->next=p;
p->next=NULL;
}
}
}
else
{
head=p;
head->next=NULL;
}
Write(head);
printf("---添加成功!---\n");
printf("\n");
printf(">>>现在的学生信息为:\n");
Show(head);
return head;//如果插入在第一个以前,则head变了,于是需要返回head
}
void Show(Student *head) //浏览数据
{
int n=1;
if(head)
{
printf("*************************************************************************************************************************\n");
printf("║序号 ║║ 学号 ║ 姓名 ║ 年龄 ║ 性别 ║ 出生年月 ║║ 地址 ║║ 电话 ║║ 邮箱 ║\n");
while(head)
{
printf(" %d\t %d\t %s\t %d\t %s\t %s\t %s\t %s\t %s\n ",
n,head->number,head->name,head->age,head->sex,head->birthday,head->address,head->phone,head->email);
head=head->next;
n++;
}
printf("*************************************************************************************************************************\n");
}
else
printf("此文件为空,请先输入数据");
system("pause");
}
void findmenu()
{
printf("\n\n\n");
printf("\t\t\t☆☆学生信息查找☆☆\n");
printf("\t\t---------------------------------------\n");
printf("\t\t\t 1 按学号查找 \n");
printf("\t\t\t 2 按姓名查找 \n");
printf("\t\t---------------------------------------\n");
printf("\t\t\t请输入菜单选项1-2:");
}
Student *Ffind(Student *head)//查询函数
{
int k=1;
if(head) //判断
{
system("cls");
findmenu();
int judge;
scanf("%d",&judge);
Student *p1;
p1=head;
printf("\t\t\t 输入你想查找的人:");
if(judge==1)
{
int num;
scanf("%d",&num);
while(p1->number!=num)
{
p1=p1->next;
if(!p1)
{
puts("此人不存在!\n");
k=0;
break;
}
}
}
else
{
char name[20];
scanf("%s",&name);
while(strcmp(name,p1->name))
{
p1=p1->next;
if(!p1)
{
puts("此人不存在!\n");
k=0;
break;
}
}
}
if(k)
{
printf("\n");
printf("║ 学号 ║ 姓名 ║ 年龄 ║ 性别 ║ 出生年月 ║║ 地址 ║║ 电话 ║║ 邮箱 ║\n");
printf(" %d\t %s\t %d\t %s\t %s\t %s\t %s\t %s\n ",
p1->number,p1->name,p1->age,p1->sex,p1->birthday,p1->address,p1->phone,p1->email);
}
}
else
{
k=0;
printf("此文件为空,请先输入数据");
}
system("pause");
if(k)
return head;
else
return NULL;
}
Student *Find(Student *head)//查找函数(用于修改函数中)界面比Ffind函数简洁
{
int k=1;
if(head) //判断
{
printf("---请先查找要修改的人---\n");
printf(">>>按学号查找请按1\t按姓名查找请按2\n");//选择根据名字还是根据学号查询
int judge;
scanf("%d",&judge);
Student *p1;
p1=head;
printf("输入你想修改的人:");
if(judge==1)
{
int num;
scanf("%d",&num);
while(head->number!=num)
{
head=head->next;
if(!head)
{
puts("此人不存在!\n");
k=0;
break;
}
}
}
else
{
char name[20];
scanf("%s",&name);
while(strcmp(name,head->name))
{
head=head->next;
if(!head)
{
puts("此人不存在!\n");
k=0;
break;
}
}
}
}
else
{
k=0;
puts("此文件为空!");
}
system("pause");
if(k)
return head;
else
return NULL;
}
void xiugaimenu()
{
printf("\n\n\n");
printf("\t\t\t☆☆学生信息修改☆☆\n");
printf("\t\t---------------------------------------\n");
printf("\t\t\t 1 修改学号 \n");
printf("\t\t\t 2 修改姓名 \n");
printf("\t\t\t 3 修改年龄 \n");
printf("\t\t\t 4 修改性别 \n");
printf("\t\t\t 5 修改生日 \n");
printf("\t\t\t 6 修改地址 \n");
printf("\t\t\t 7 修改电话 \n");
printf("\t\t\t 8 修改邮箱 \n");
printf("\t\t---------------------------------------\n");
printf("\t\t\t请输入菜单选项1-8:");
}
Student *Change(Student *headI)//修改信息
{
int n;
Student *head=Find(headI);//由于之前已经定义过find函数,故此处不需要再搜索,直接调用find函数即可
getchar();
system("cls");
xiugaimenu();
if(head) //判断
{
scanf("%d",&n);
switch(n)
{
case 1:
{
printf("\t\t\t 学号修改为:");
scanf("%d",&head->number);
printf("\t\t\t 修改成功!");//
system("pause");
break;
}
case 2:
{
printf("\t\t\t 姓名修改为:");
scanf("%s",&head->name);
printf("\t\t\t 修改成功!");
system("pause");
break;
}
case 3:
{
printf("\t\t\t 年龄修改为:");
scanf("%d",&head->age);
printf("\t\t\t 修改成功!");
system("pause");
break;
}
case 4:
{
printf("\t\t\t 性别修改为:");
scanf("%s",&head->sex);
printf("\t\t\t 修改成功!");
system("pause");
break;
}
case 5:
{
printf("\t\t\t 生日修改为:");
scanf("%s",&head->birthday);
printf("\t\t\t 修改成功!");
break;
}
case 6:
{
printf("\t\t\t 地址修改为:");
scanf("%s",&head->address);
printf("\t\t\t 修改成功!");
system("pause");
break;
}
case 7:
{
printf("\t\t\t 电话修改为:");
scanf("%s",&head->phone);
printf("\t\t\t 修改成功!");
break;
}
case 8:
{
printf("\t\t\t 邮箱修改为:");
scanf("%s",&head->email);
printf("\t\t\t 修改成功!");
system("pause");
break;
}
default:
printf("选项错误!按任意键继续!");
getchar();
system("cls");
}
head=Sort(headI);
Write(headI);
}
return headI;
}
void menu()//主菜单
{
system("cls");//清空屏幕
printf("\t -----------------------------------------------------\n");
printf("\t \n");
printf("\t ☆☆☆ 欢迎使用学生信息管理系统 ☆☆☆ ");
printf("\t \n");
printf("\t -----------------------------------------------------\n");
printf("\t | 1 → 录入学生信息 |\n");
printf("\t | 2 → 浏览学生信息 |\n");
printf("\t | 3 → 查找学生信息 |\n");
printf("\t | 4 → 修改学生信息 |\n");
printf("\t | 5 → 添加学生信息 |\n");
printf("\t | 6 → 删除学生信息 |\n");
printf("\t | 7 → 退出管理系统 |\n");
printf("\t -----------------------------------------------------\n");
printf("\t\t\t\t\t\t");
system("date/t");
printf("\t\t\t\t\t\t ");
system("time/t");
printf("\t请选择菜单选项1-7:");
}
//主函数
int main()
{
system("title 学生管理系统");
system("color F4");
system("mode 130,100");
menu();//初始化页面
Student *head=NULL;//创建临时链表
head=Read();//每次先从文件读出链表
int n;
while(1)
{
scanf("%d",&n);
switch(n)
{
case 1:
system("cls");
head=Input();
break;
case 2:
system("cls");
Show(head);
break;
case 3:
system("cls");
Ffind(head);
break;
case 4:
system("cls");
head=Change(head);
break;
case 5:
system("cls");
head=Add(head);
break;
case 6:
system("cls");
head=Delete(head);
break;
case 7:
printf("\n\t\t★★★感谢您的使用,期待下一次相遇★★★\n");
exit(0);
break;
}
menu();
}
return 0;
}