〔问题描述〕学生成绩管理是学校教务部门日常工作的重要组成部分,其处理信息量很大。本项目是对学生成绩管理的简单模拟,用菜单选择方式完成下列功能:输入输出学生成绩数据;学生成绩查询;添加学生成绩数据;修改学生成绩数据;删除学生成绩数据;按成绩排序等。
〔基本要求〕本项目的实质是完成对学生成绩信息的建立、查找、插入、修改、删除、排序等功能,可以首先定义数据结构(顺序表或者链表),然后将每个功能写成一个函数来完成对数据的操作,最后完成主函数以验证各个函数功能并得出运行结果。学生的考试成绩必须通过键盘输入,且需对输出进行格式控制。
代码如下:
#include
#include
#include
// 学生成绩信息
typedef struct data
{
/* data */
int id;
char *name;
float math;
float english;
float science;
} Data;
// 学生列表
typedef struct node
{
/* data */
Data *data;
struct node *next; // 下一个节点
} Node;
/**
* @brief 创建新节点
* @param flag 0用于创建头结点,1用于创建普通节点
* @return 一个Node节点
*/
Node *createNode(int flag)
{
Node *node = (Node *)malloc(sizeof(Node));
if (flag == 0)
{
node->data = NULL;
node->next = NULL;
}
else
{
node->data = (Data *)malloc(sizeof(Data));
node->next = NULL;
}
return node;
}
/**
* @brief 打印所有学生的成绩信息
* @param head 学生列表的头结点
* @return 无
*/
void printfStuInfo(Node *head)
{
if (head == NULL || head->next == NULL)
{
printf("表中无数据,请先添加数据\n");
}
for (head = head->next; head != NULL; head = head->next)
{
Data *node = head->data;
printf("id:%-5d姓名:%-6s英语:%-6.1f数学:%-6.1f科学:%-6.1f\n", node->id, node->name, node->english, node->math, node->science);
}
}
/**
* @brief 向节点写入成绩信息
* @param data 存储成绩信息的变量
* @param id 学生id
* @param name[] 学生姓名
* @param english 英语成绩
* @param math 数学成绩
* @param science 科学成绩
* @return 无
*/
void initNodeInfo(Data *data, int id, char name[], float english, float math, float science)
{
data->id = id;
data->name = name;
data->english = english;
data->math = math;
data->science = science;
}
/**
* @brief 向学生列表中添加节点
* @param head 学生列表的头结点
* @param node 要添加的节点
* @return 无
*/
void pushList(Node *head, Node *node)
{
Node *temp = head;
Node *last = head;
for (; temp->next != NULL; temp = temp->next)
{
if (temp->data == NULL)
{
continue;
}
if (temp->data->id == node->data->id)
{
printf("这个id已经存在了,请重新输入\n");
return;
}
if (temp->data->id > node->data->id)
{
break;
}
last = temp;
}
if (temp->next != NULL)
{
node->next = last->next;
last->next = node;
}
else if (temp->data == NULL)
{
temp->next = node;
}
else
{
if (temp->data->id == node->data->id)
{
printf("这个id已经存在了,请重新输入\n");
return;
}
}
printf("导入成功\n");
}
/**
* @brief 更改学生节点的成绩信息
* @param head 学生列表的头结点
* @param id 需要更改学生的id
* @param flag 更改哪一门科目,1为英语,2为数学,3为科学
* @param score 更改的分数
* @return 无
*/
void changeStuInfo(Node *head, int id, int flag, float score)
{
Node *temp = head;
if (temp == NULL || head->next == NULL)
{
printf("表中无数据,请先添加数据\n");
return;
}
for (temp = temp->next; temp != NULL; temp = temp->next)
{
if (temp->data->id == id)
{
if (flag == 1)
{
temp->data->english = score;
}
if (flag == 2)
{
temp->data->math = score;
}
if (flag == 3)
{
temp->data->science = score;
}
printf("修改成功\n");
break;
}
}
if (temp == NULL)
{
printf("未查找到当前id对应的数据,请重新输入\n");
}
}
/**
* @brief 删除学生成绩信息
* @param head 学生列表的头结点
* @param id 需要删除的学生id
* @return 无
*/
void removeStuInfo(Node *head, int id)
{
Node *temp = head;
Node *last = head;
if (temp == NULL || temp->next == NULL)
{
printf("表中无数据,请先添加数据\n");
}
for (temp = temp->next; temp != NULL; temp = temp->next)
{
if (temp->data->id == id)
{
last->next = temp->next;
free(temp);
break;
}
last = temp;
printf("删除成功\n");
}
}
/**
* @brief 查找某个学生的成绩信息
* @param head 学生列表的头结点
* @param id 需要查找学生的id
* @return 无
*/
void searchStuInfo(Node *head, int id)
{
Node *temp = head;
if (temp == NULL || temp->next == NULL)
{
printf("表中无数据,请先添加数据\n");
}
for (temp = temp->next; temp != NULL; temp = temp->next)
{
if (temp->data->id == id)
{
Data *node = temp->data;
printf("id:%-5d姓名:%-6s英语:%-6.1f数学:%-6.1f科学:%-6.1f\n", node->id, node->name, node->english, node->math, node->science);
break;
}
}
if (temp == NULL)
{
printf("未查找到该id对应的学生信息,请重新输入");
}
}
/**
* @brief 复制节点
* @param id 学生id
* @param name[] 学生姓名
* @param english 英语分数
* @param math 数学分数
* @param science 科学分数
* @return 无
*/
Node *cloneNode(int id, char name[], float english, float math, float science)
{
Node *node = createNode(1);
initNodeInfo(node->data, id, name, english, math, science);
return node;
}
/**
* @brief 对链表进行排序
* @param head 待排序链表的头结点
* @param flag 按照哪门科目排序1为英语2为数学3为科学
* @param tag true为递减false为递增
* @return 无
*/
void SortStuList(Node *head, int flag, bool tag)
{
Node *sort = createNode(0);
Node *pre, *p, *q;
Node *tail = NULL;
float score1, score2;
if (head == NULL || head->next == NULL)
{
printf("表中无数据,请先添加数据\n");
}
for (Node *temp = head->next; temp != NULL; temp = temp->next)
{
Node *node = cloneNode(temp->data->id, temp->data->name, temp->data->english, temp->data->math, temp->data->science);
pushList(sort, node);
}
while (sort->next != tail)
{
pre = sort;
p = pre->next;
q = p->next;
while (p->next != tail)
{
if (flag == 1)
{
score1 = p->data->english;
score2 = q->data->english;
}
else if (flag == 2)
{
score1 = p->data->math;
score1 = q->data->math;
}
else if (flag == 3)
{
score1 = p->data->science;
score2 = q->data->science;
}
else
{
printf("请输入正确的标识");
return;
}
if (tag == true)
{
if (score1 > score2)
{
pre->next = q;
p->next = q->next;
q->next = p;
}
else
{
p = p->next;
}
}
else
{
if (score1 < score2)
{
pre->next = q;
p->next = q->next;
q->next = p;
}
else
{
p = p->next;
}
}
q = p->next;
pre = pre->next;
}
tail = p;
}
printfStuInfo(sort);
}
int main()
{
Node *head = NULL;
int tabId;
int stuNumber;
int id;
char name[10];
float english;
float math;
float science;
int flag;
float score;
bool tag;
while (true)
{
printf("请选择你要执行的功能:\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");
scanf("%d", &tabId);
switch (tabId)
{
case 1:
if (head == NULL)
{
head = createNode(0);
printf("列表创建成功\n");
}
else
{
printf("已经创建列表,请勿重复创建\n");
}
break;
case 2:
if (head == NULL)
{
printf("列表还未创建,请先创建学生列表\n");
}
else
{
printf("请输入导入学生的数量:");
scanf("%d", &stuNumber);
for (int i = 1; i <= stuNumber; i++)
{
printf("请输入第%d位学生的id:", i);
scanf("%d", &id);
printf("请输入第%d位学生的姓名:", i);
scanf("%s", name);
while (true)
{
printf("请输入第%d位学生的英语成绩:", i);
scanf("%f", &english);
if (english < 0 || english > 100)
{
printf("分数只能大于等于0分小于等于100分");
}
else
{
break;
}
}
while (true)
{
printf("请输入第%d位学生的数学成绩:", i);
scanf("%f", &math);
if (english < 0 || english > 100)
{
printf("分数只能大于等于0分小于等于100分");
}
else
{
break;
}
}
while (true)
{
printf("请输入第%d位学生的科学成绩:", i);
scanf("%f", &science);
if (english < 0 || english > 100)
{
printf("分数只能大于等于0分小于等于100分");
}
else
{
break;
}
}
Node *node = createNode(1);
initNodeInfo(node->data, id, name, english, math, science);
pushList(head, node);
}
}
break;
case 3:
if (head == NULL)
{
printf("列表还未创建,请先创建学生列表\n");
}
else
{
printf("请输入要修改学生的id:");
scanf("%d", &id);
while (true)
{
printf("请输入要修改的科目(1为英语;2为数学;3为科学):");
scanf("%d", &flag);
if (flag == 1 || flag == 2 || flag == 3)
{
break;
}
else
{
printf("请输入正确的值\n");
}
}
while (true)
{
printf("请输入要修改的值:");
scanf("%f", &score);
if (score < 0 || score > 100)
{
printf("分数只能大于等于0分小于等于100分\n");
}
else
{
break;
}
}
changeStuInfo(head, id, flag, score);
}
break;
case 4:
if (head == NULL)
{
printf("列表还未创建,请先创建学生列表\n");
}
else
{
printf("请输入要删除的学生id:");
scanf("%d", &id);
removeStuInfo(head, id);
}
break;
case 5:
if (head == NULL)
{
printf("列表还未创建,请先创建学生列表\n");
}
else
{
printf("请输入你想查找的学生id:");
scanf("%d", &id);
searchStuInfo(head, id);
}
break;
case 6:
if (head == NULL)
{
printf("列表还未创建,请先创建学生列表\n");
}
else
{
printfStuInfo(head);
}
break;
case 7:
if (head == NULL)
{
printf("列表还未创建,请先创建学生列表\n");
}
else
{
while (true)
{
printf("请选择递增还是递减(0为递增1为递减):");
scanf("%d", &tag);
if (tag != 1 && tag != 0)
{
printf("请输入正确的值\n");
}
else
{
break;
}
}
while (true)
{
printf("请输入要修改的科目(1为英语;2为数学;3为科学):");
scanf("%d", &flag);
if (flag == 1 || flag == 2 || flag == 3)
{
break;
}
else
{
printf("请输入正确的值\n");
}
}
SortStuList(head, flag, tag);
}
break;
case 8:
printf("再见");
return 0;
default:
printf("请输入有效值\n");
break;
}
}
return 0;
}