**题目说明**
每个学生的信息包括:学号、姓名、性别、手机号码、数学分数、语文分数。程序使用链表结构完成以下管理功能:
扩展功能:
7. 支持从Excel表格导入学生数据
8. 支持将链表中的内容导出到Excel表格
9. 对人数、性别、分数支持简单的统计功能,如总体人数,男女比例,各区间分数百分比计算等
这里笔者指出当初在写之前搜索到的同题项目的大佬解答,留下链接: https://blog.csdn.net/weixin_42422341/article/details/86777562
放源代码前指出本项目要注意的几点:
1.文件!!导入导出的Excel文件都在了桌面,记得修改路径!
2.数据的输入的格式要求最好提前设置(在导入的Excel文件中笔者设置了电话号码的长度为11位,姓名长度为2位)
3.在项目验收时可能会要求判断输入错误的数据类型时的情况,读者可以自己自行添加代码完成需求
*4.数据的导入有两种方式,主界面输入“1”可进行手动输入,或者输入“9”直接导入已保存的数据,导出的文件为空文件,导入的文件如下(可自行添加/设置)
tips:喜欢还不赞,年轻人你要耗子尾汁,好好饭思!
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef struct Node
{
int id; //学号
char name[20]; //姓名
char sex; //性别
char num[20]; //手机号码
int math; //数学分数
int chinese; //语文分数
struct Node *next;
}Node;
typedef struct Node *LinkList;
Status InitList(LinkList *L); //初始化链表
Status ListEmpty(LinkList L); //判断链表是否为空
Status add(LinkList *L); //在链表尾部添加结点 ,并更新文件
Status deleteStu(LinkList *L); //按学号删除其中某一个结点,并更新文件
Status modify(LinkList *L); //修改某一个结点,并更新文件
Status get(LinkList *L); //获取其中某一个或某一类结点
Status sort(LinkList *L); //给链表重排序打印,并更新文件
Status ListTraverse(LinkList L); //遍历链表,并打印
Status countAll(LinkList *L); //学生信息统计
Status excelOut(LinkList *L); //将链表导出保存为csv文件
void Print(Node c); //结点打印函数
void NewList(LinkList *L); //创建指定数目的结点
void excelIn(LinkList *L); //从指定csv文件中导出数据,存入链表
void menu(LinkList *L); //主菜单界面
int ListLength(LinkList L);
int ListLength(LinkList L)
{
int i=0;
LinkList p=L->next; /* p指向第一个结点 */
while(p)
{
i++;
p=p->next;
}
return i;
}
Status InitList(LinkList *L)
{
*L=(LinkList)malloc(sizeof(Node)); /* 产生头结点,并使L指向此头结点 */
if(!(*L)) /* 存储分配失败 */
return ERROR;
(*L)->next=NULL; /* 指针域为空 */
return OK;
}
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty(LinkList L)
{
if(L->next)
return FALSE;
else
return TRUE;
}
void Print(Node c)
{
printf("%d ",c.id);
printf("%s ",c.name);
printf("%c ",c.sex);
printf("%s ",c.num);
printf("%d ",c.math);
printf("%d\n",c.chinese);
}
//尾插法插入数据
Status add(LinkList *L)
{
LinkList p,e;
p = *L;
e = (Node *)malloc(sizeof(Node)); /* 生成新结点 */
printf("请输入学生信息,格式如下\n");
printf("学号 姓名 性别(f/m) 电话 数学成绩 语文成绩\n");
scanf("%d %s %c %s %d %d",&e->id,&e->name,&e->sex,&e->num,&e->math,&e->chinese);
if(getchar()!='\n'){
printf("输入错误,返回主界面\n");
system("pause");
return 0;
}
while (p->next) //循环寻找最后一个节点
{
if((e->id)==(p->id))
{
printf("学生信息重复,返回界面\n");
system("pause");
return 0;
}
p = p->next;
}
e->next = NULL;
p->next = e;
printf("添加成功\n");
excelOut(L);
return OK;
}
Status deleteStu(LinkList *L)
{
LinkList p;
if(ListEmpty(*L)){
printf("链表为空,请先输入数据\n");
system("pause");
return ERROR;
}//链表为空
p = (*L);
int id;
printf("输入待删除学生的学号\n");
scanf("%d",&id);
while (p->next&&(p->next->id!=id)) /* 寻找指向指定id的结点 */
{
p = p->next;
}
if (!(p->next)) {
printf("不存在该学号的学生,删除失败\n");
system("pause");
return ERROR;
} //不存在该学号的学生
p->next = p->next->next; //将该结点指向目标结点的后一个结点
printf("删除成功\n");
excelOut(L); //导出之Excel表
return OK;
}
//先查询出数据后进行修改
Status modify(LinkList *L){
LinkList p;
p = (*L)->next;
int id;
if(ListEmpty(*L)){
printf("链表为空,请先输入数据\n");
system("pause");
return ERROR;
}//链表为空
printf("输入待修改学生的学号\n");
scanf("%d",&id);
while (p->id!=id) /* 寻找指定id的结点 */
{
p = p->next;
}
if (p==NULL){
printf("该学号的学生不存在\n");
return ERROR;
} /* 查询完整个链表,不存在该学号的学生 */
printf("待修改学生信息为\n");
Print(*p);
printf("\n请选择修改项目\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("请选择(1-8):[ ]\b\b");
int i;
scanf("%d",&i);
switch(i){
case 1:
printf("将学号修改为\n");
scanf("%d",&p->id);
printf("修改后该学生信息为:\n");
Print(*p);
excelOut(L);
break;
case 2:
printf("将姓名修改为\n");
scanf("%d",&p->name);
printf("修改后该学生信息为:\n");
Print(*p);
excelOut(L);
break;
case 3:
printf("将性别修改为\n");
scanf("%d",&p->sex);
printf("修改后该学生信息为:\n");
Print(*p);
excelOut(L);
break;
case 4:
printf("将电话号码修改为\n");
scanf("%s",&p->num);
printf("修改后该学生信息为:\n");
Print(*p);
excelOut(L);
break;
case 5:
printf("将数学成绩修改为\n");
scanf("%d",&p->math);
printf("修改后该学生信息为:\n");
Print(*p);
excelOut(L);
break;
case 6:
printf("将语文成绩修改为\n");
scanf("%d",&p->chinese);
printf("修改后该学生信息为:\n");
Print(*p);
excelOut(L);
break;
case 7:
printf("将学生信息修改为\n");
scanf("%d %s %c %s %d %d",&p->id,p->name,&p->sex,&p->num,&p->math,&p->chinese);
printf("修改后该学生信息为:\n");
Print(*p);
excelOut(L);
break;
case 8:
system("cls");
modify(L);
default:
printf("输入错误,请重新输入\n");
system("pause");
system("cls");
modify(L);
}
}
//待修改 按学号修改
Status get(LinkList *L){
int id;
LinkList p=(*L)->next;
if(ListEmpty(*L)){
printf("链表为空,请先输入数据\n");
system("pause");
return ERROR;
}//链表为空
printf("输入待查询学生的学号\n");
scanf("%d",&id);
while(p)
{
if(p->id==id){
printf("查询成功\n");
Print(*p);
system("pause");
return OK;
}
p=p->next;
}
printf("查询失败,不存在该学号的学生\n");
system("pause");
return ERROR;
}
//排序
Status sort(LinkList *L){
LinkList p,m,n,pre;
int i;
if(ListEmpty(*L)){
printf("链表为空,请先输入数据\n");
system("pause");
return ERROR;
}//链表为空
int len=ListLength(*L);
int j=0;
printf("\t\t1.按学号排序\n");
printf("\t\t2.按数学成绩排序\n");
printf("\t\t3.按语文成绩排序\n");
printf("\t\t请选择(1-3):[ ]\b\b\b");
scanf("%d",&i);
printf("开始排序\n");
switch(i){
case 1:
while(j<len-1){
p=*L;
while((p->next!=NULL)&&(p->next->next!=NULL)){
if((p->next->id)>(p->next->next->id)){
m=p->next->next;
n=p->next;
p->next=m;
n->next=m->next;
m->next=n;
}
p=p->next;
}
j=j+1;
}
printf("排序成功");
printf("重排序后为\n");
ListTraverse(*L);
excelOut(L);
break;
case 2:
while(j<len-1){
p=*L;m=*L;n=*L;
while((p->next!=NULL)&&(p->next->next!=NULL)){
if((p->next->math)<(p->next->next->math)){
m=p->next->next;
n=p->next;
p->next=m;
n->next=m->next;
m->next=n;
}
p=p->next;
}
j=j+1;
}
printf("排序成功");
printf("重排序后为\n");
ListTraverse(*L);
excelOut(L);
break;
case 3:
while(j<len-1){
p=*L;m=*L;n=*L;
while((p->next!=NULL)&&(p->next->next!=NULL)){
if((p->next->chinese)<(p->next->next->chinese)){
m=p->next->next;
n=p->next;
p->next=m;
n->next=m->next;
m->next=n;
}
p=p->next;
}
j=j+1;
}
printf("排序成功");
printf("重排序后为\n");
ListTraverse(*L);
excelOut(L);
break;
default:
printf("无效输入,请重新输入\n");
system("pause");
system("cls");
sort(L);
}
return 0;
}
//遍历数据,用于检测数据
Status ListTraverse(LinkList L)
{
if(ListEmpty(L)){
printf("链表为空,请先输入数据\n");
system("pause");
return ERROR;
}//链表为空
LinkList p=L->next;
while(p)
{
Print(*p);
p=p->next;
}
system("pause");
return OK;
}
void NewList(LinkList *L)
{
LinkList p,r;
int i,n;
printf("输入学生的数量:\n");
scanf("%d",&n);
*L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */
r=*L; /* r为指向尾部的结点 */
printf("请输入学生信息,格式如下\n");
printf("学号 姓名 性别(m\f) 号码 数学成绩 语文成绩\n");
for (i=0; i<n; i++) {
printf("%d: ",i+1);
p = (Node *)malloc(sizeof(Node)); /* 生成新结点 */
scanf("%d %s %c %s %d %d",&p->id,p->name,&p->sex,&p->num,&p->math,&p->chinese);
if(p->sex!='m'&&p->sex!='f')
{
printf("性别输入错误");
system("pause");
return ;
}
r->next=p;
r = p;
}
r->next = NULL; /* 表示当前链表结束 */
printf("输入结束\n");
system("pause");
}
//拓展功能
Status countAll(LinkList *L){
if(ListEmpty(*L)){
printf("链表为空,请先输入数据\n");
system("pause");
return 0;
}//链表为空
printf("学生信息情况统计如下:\n");
LinkList p;
p = (*L)->next;
int male,female,num;
int badmale=0,okmale=0,okkmale=0,goodmale=0,badfemale=0,okfemale=0,okkfemale=0,goodfemale=0,summath=0,sumchinese=0,averagemath=0,averagechinese=0;
//男生人数,女生人数,总人数和不及格(<60),及格(60-70),良好(70-90),优秀(90-100)分数标准
double radio;
while(p){
num=num+1;
if(p->sex=='m'){
male=male+1;
}else{
female=female+1;
}
switch(p->math/10){
case 1:
case 2:
case 3:
case 4:
case 5:
badmale=badmale+1;
break;
case 6:
okmale=okmale+1;
break;
case 7:
case 8:
case 9:
okkmale=okkmale+1;
case 10:
goodmale=goodmale+1;
}
switch(p->chinese/10){
case 1:
case 2:
case 3:
case 4:
case 5:
badfemale=badfemale+1;
break;
case 6:
okfemale=okfemale+1;
break;
case 7:
case 8:
case 9:
okkfemale=okkfemale+1;
case 10:
goodfemale=goodfemale+1;
}
summath=summath+p->math;
sumchinese=sumchinese+p->chinese;
p=p->next;
}
printf("总人数为 %d\n",num);
printf("男生人数为 %d\n",male);
printf("女生人数为 %d\n",female);
radio=male*1.0/num;
printf("男女比例为 %.1f : %.1f\n",radio,(1-radio));
printf("数学成绩\n");
printf("不及格: %d人\t",badmale);
printf("及格: %d人\t",okmale);
printf("良好: %d人\t",okkmale);
printf("优秀: %d人\n",goodmale);
averagemath=summath*1.0/num;
printf("数学成绩平均分为: %d\n",averagemath);
printf("语文成绩\n");
printf("不及格: %d人\t",badfemale);
printf("及格: %d人\t",okfemale);
printf("良好: %d人\t",okfemale);
printf("优秀: %d人\n",goodfemale);
averagechinese=sumchinese/num;
printf("语文成绩平均分为: %d\n",averagechinese);
system("pause");
return 1;
}
Status excelOut(LinkList *L){
if(ListEmpty(*L)){
printf("链表为空,导出失败\n");
system("pause");
return 0;
} //链表为空
FILE *fp=NULL;
fp=fopen("C:\\Users\\86150\\Desktop\\ttt.csv","w+");
LinkList p;
p=(*L)->next;
printf("开始保存\n");
while(p){
fprintf(fp,"%d,%s,%c,%s,%d,%d\n",p->id,p->name,p->sex,p->num,p->math,p->chinese);
p=p->next;
}
printf("保存成功\n");
system("pause");
fclose(fp);
return 1;
}
void excelIn(LinkList *L){
FILE *fp;
fp=fopen("C:\\Users\\86150\\Desktop\\3.csv","r");
LinkList p,e,next;
p=(*L);
printf("开始读入\n");
while(!feof(fp)){
e = (Node *)malloc(sizeof(Node)); /* 生成新结点 */
fscanf(fp,"%d,%2s,%c,%11s,%d,%d\n",&e->id,e->name,&e->sex,e->num,&e->math,&e->chinese);
e->next=NULL;
p->next=e;
p=p->next;
}
printf("读入成功\n");
system("pause");
fclose(fp);
}
void menu(LinkList *L){
int n;
printf("\t---------------学生个人信息管理系统---------------\n");
printf("\t\t\t1.创建学生管理系统(手动输入创建)\n");
printf("\t\t\t2.添加学生信息\n");
printf("\t\t\t3.删除学生信息\n");
printf("\t\t\t4.修改学生信息\n");
printf("\t\t\t5.查询学生信息\n");
printf("\t\t\t6.排序后输出\n");
printf("\t\t\t7.信息检查\n");
printf("\t\t\t8.信息统计\n");
printf("\t\t\t9.Excel数据导入\n");
printf("\t\t\t10.Excel数据导出\n");
printf("\t\t\t11.退出\n");
printf("\t\t\t请选择(1-11):[ ]\b\b\b");
scanf("%d",&n);
switch(n){
case 1:
system("cls");
NewList(L);//初始化学生管理系统,输入指定数目的学生信息
break;
case 2:
system("cls");
add(L);//添加学生信息
break;
case 3:
system("cls");
deleteStu(L);//删除指定学生
break;
case 4:
system("cls");
modify(L);//修改学生信息
break;
case 5:
system("cls");
get(L);//查找指定学生
break;
case 6:
system("cls");
sort(L);//排序输出
break;
case 7:
system("cls");
ListTraverse(*L);//遍历
break;
case 8:
system("cls");
countAll(L);
break;//学生信息情况统计
case 9:
system("cls");
excelIn(L);
break;
case 10:
system("cls");
excelOut(L);
break;
case 11:
exit(0);
default :
system("cls");
printf("无效输入,请重新输入\n");
system("pause");
break;
}
}
int main(){
LinkList stu;
InitList(&stu);
while(1){
system("cls");
menu(&stu);
}
}