#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<stdbool.h>
#define NO_LENGTH 20
#define NAME_LENGTH 11
typedef struct Student {
char number[NO_LENGTH]; //学号
char name[NAME_LENGTH]; //姓名
char sex[6]; //性别
int age; //年龄
char phone[NO_LENGTH]; //手机号
char box[NO_LENGTH]; //邮箱
double grade; //成绩
} st;
typedef struct node {
struct Student data;
struct node* next;
} Node,*Link;
//提示菜单:
void myMenu() {
printf("* * * * * * * * * * 菜 单 * * * * * * * * * *\n");
printf(" 1 增加学生记录 2 删除学生记录 \n");
printf(" 3 查找学生记录 4 修改学生记录 \n");
printf(" 5 统计学生人数 6 显示学生记录 \n");
printf(" 7 学生成绩排名 8 退出系统 \n");
printf(" * * * * * * * * * * * * * * * * * * * * * * * *\n");
}
//尾插:按顺序存放
Link newList(struct Student list[],int n) {
Link head = malloc(sizeof(Node));
head->next = NULL;
Link rear = head;
for(int i = 0; i < n; i++) {
Link node = malloc(sizeof(Node));
node->data = list[i];
node->next = NULL;
rear->next = node;
rear = node;
}
return head;
}
//遍历:
void displayNode(Link head) {
Link p = head->next;
int count = 0;
while(p != NULL) {
printf("\n第%d个学生的学号、姓名、性别、年龄分别是:%s %s %s %d\n",
count+1,p->data.number,p->data.name,p->data.sex,p->data.age);
printf("手机号是:%s , 邮箱是: %s,总成绩是:%.2f\n",p->data.phone,p->data.box,p->data.grade);
count++;
p = p->next;
}
printf("\n");
}
//删除记录:(查学号删除)
bool deleteNode(Link head,char number[]) {
if(head == NULL || head->next == NULL) {
return false;
}
Link p = head->next;
Link q = head;
while(p != NULL) {
if(strcmp(p->data.number,number) == 0) {
q->next = p->next;
free(p);
return true;
} else {
q = p;
p = p->next;
}
}
return false;
}
//选择记录插入:
bool insertNode(Link head,int i,struct Student newdata) {
Link p = head;
int count = 1;
while(p != NULL && count < i) {
p = p->next;
count++;
}
if(p == NULL) {
return false;
} else {
Link node = malloc(sizeof(Node));
node->data = newdata;
node->next= p->next;
p->next = node;
return true;
}
}
//按学生学号大小增加学生记录:
void inputStudent(Link l) {
printf("请分别输入学生的学号、姓名、性别、年龄、手机号、邮箱、总成绩:\n");
scanf("%s%s%s%d%s%s%lf",l->data.number,l->data.name,l->data.sex,&l->data.age,
l->data.phone,l->data.box,&l->data.grade);
//每个新创建的节点的next域都初始化为NULL
l->next = NULL;
}
//按学号大小插入新结点
bool addNode(Link head) {
Link p = head->next;
Link q = head; //q指向head后面的第一个有效节点
Link node = malloc(sizeof(Node));
inputStudent(node);
if(head->next == NULL) //没有数据时插入第一个数据
head->next = node;
else {
while(p != NULL) {
if (strcmp(node->data.number,p->data.number) < 0) {
//如果node节点的学号比p节点的学号小,则插在p的前面,完成插入后,提前退出子程序
q->next = node;
node->next = p;
return true;
} else {
//如果node节点的学号比p节点的学号大,继续向后移动指针(依然保持pq一前一后)
q = p;
p = p->next;
}
}
//如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
q->next = node;
}
return true;
}
//统计学生人数:
int countNode(Link head) {
Link p;
int count = 0;
p = head->next;
while(p != NULL) {
count ++;
p = p->next;
}
return count;
}
//释放结点;
void clearLink(Link head) {
Link q;
while(head->next != NULL) {
q = head;
free(q);
head = head->next;
}
free(head);
}
//查询学生记录
bool queryNode(Link head) {
Link p = head->next;
int key;
printf("输入key(1~5),查询方式(1:姓名 2:学号 3:手机号 4:邮箱 5:年龄范围) :");
scanf("%d",&key);
if(key != 5) {
char value[20];
printf("\n请输入查询关键词:");
scanf("%s",value);
char middle[NO_LENGTH];
switch(key) {
case 1:
strcpy(middle,p->data.name);
break;
case 2:
strcpy(middle,p->data.number);
break;
case 3:
strcpy(middle,p->data.phone);
break;
case 4:
strcpy(middle,p->data.box);
}
while(p != NULL) {
if(strcmp(middle,value) == 0) {
printf("\n查询成功!\n");
printf("学生信息:姓名:%s 学号:%s 性别:%s 年龄:%d \n手机号:%s 邮箱:%s 总成绩:%.2f\n",
p->data.name,p->data.number,p->data.sex,p->data.age,p->data.phone,p->data.box,p->data.grade);
printf("\n");
}
p = p->next;
if(p != NULL) {
if(key == 1) strcpy(middle,p->data.name);
else if(key == 2) strcpy(middle,p->data.number);
else if(key == 3) strcpy(middle,p->data.phone);
else if(key == 4) strcpy(middle,p->data.box);
}
}
}
//指定年龄范围查询:
else {
int age1,age2;
int key = 0;
printf("请输入年龄范围:");
scanf("%d%d",&age1,&age2);
while(p != NULL) {
if(age1 <= p->data.age && p->data.age <= age2) {
printf("\n查询成功!\n");
key = 1;//说明已经有找到的
printf("学生信息:姓名:%s 学号:%s 性别:%s 年龄:%d \n手机号:%s 邮箱:%s 总成绩:%.2f\n",
p->data.name,p->data.number,p->data.sex,p->data.age,p->data.phone,p->data.box,p->data.grade);
printf("\n");
}
p = p->next;
}
if(key == 1) {
return true;
}
}
return false;
}
//修改学生信息
bool modifyNode(Link head) {
Link p = head->next;
char value[20];
printf("请输入你想要修改记录的学生姓名:");
scanf("%s",value);
while(p != NULL) {
if(strcmp(p->data.name,value) == 0) {
printf("请重新输入学生的信息:\n");
printf("输入学生的学号、姓名、性别、年龄:\n");
scanf("%s%s%s%d",p->data.number,p->data.name,p->data.sex,&p->data.age);
printf("输入学生的手机号、邮箱、总成绩:\n");
scanf("%s%s%lf",p->data.phone,p->data.box,&p->data.grade);
break;
}
p = p->next;
}
return true;
}
//输出成绩排名
bool stuScore(Link head,double data[NO_LENGTH]) {
Link p = head->next;
if(p == NULL) {
return false;
}
int i = 0,key = 0;
while(p != NULL) {
data[i] = p->data.grade;
i++;
p = p->next;
}
bubblesort(data,i);
i = 0;
for(p = head->next; p != NULL; p = p->next) {
if(p->data.grade == data[i]) {
printf("第%d名:学号:%s 姓名:%s 性别:%s 总成绩:%.2f\n",i+1,p->data.number,p->data.name,p->data.sex,p->data.grade);
p = head;
i++;
}
}
return true;
}
//冒泡排序
void bubblesort(double array[],int array_size) {
int exchange;
for(int pass = 1; pass < array_size; pass++) {
exchange = 0;
for(int i = 0; i < array_size - pass; i++) {
if(array[i] < array[i+1]) {
double temp = array[i];
array[i] = array[i+1];
array[i+1] = temp;
exchange = 1;
}
}
if(exchange == 0) break;
}
}
int main() {
//输入学生数据:
int arraysize;
printf("输入您想要记录的学生人数:");
scanf("%d",&arraysize);
st list[100];
for(int i=0; i < arraysize; i++) {
printf("第%d个学生的学号、姓名、性别、年龄、手机号、邮箱、总成绩:\n",i+1);
scanf("%s%s%s%d%s%s%lf",list[i].number,list[i].name,list[i].sex,&list[i].age,
list[i].phone,list[i].box,&list[i].grade);
printf("\n");
}
printf("\n");
Link head = newList(list,arraysize); //引入头部
double data[NO_LENGTH]; //用于作成绩排名
int count;
int select;
while(1) {
myMenu();
printf("\n请输入你的选择(1-8):"); //显示提示信息
scanf("%d",&select);
switch(select) {
case 1:
//增加学生记录
if(addNode(head))
printf("成功插入一个学生记录。\n\n");
break;
case 2:
//删除学生记录
printf("输入要修改记录的学生学号:");
char number[NO_LENGTH];
scanf("%s",number);
if(deleteNode(head,number))
printf("成功删除一个学生记录。\n\n");
else
printf("没有找到要删除的学生节点。\n\n");
break;
case 3:
//查询学生记录
if(queryNode(head))
printf("无法找到这位学生!\n");
break;
case 4:
//修改学生记录
if(modifyNode(head))
printf("成功修改一个学生记录。\n\n");
else
printf("没有找到要修改的学生节点。\n\n");
break;
case 5:
//统计学生人数
count = countNode(head);
printf("学生人数为:%d\n\n",count);
break;
case 6:
//显示学生记录
displayNode(head);
break;
case 7:
//显示学生成绩排名
stuScore(head,data);
break;
case 8:
//退出前释放内存空间
clearLink(head);
return 0;
default:
printf("输入不正确,请输入1-8之间的数!\n\n");
break;
}
}
return 0;
}