#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define NUMOFSTU 5
#define NUMOFCOURSE 6
struct student
{
int number;
char name[10];
int score[NUMOFCOURSE];
float sum;
float average;
struct student *next;
};
typedef struct student STU;
STU *firsthead;
char Menu(void);
void List(STU *head);
void AppendNode( STU *head );
void DeleteNode( STU *head );
void ChangeNode( STU *head );
void SearchNode( STU *head );
void Exit( STU *head );
int OkOrNot(char *name);
int GetNodeNumber(STU *head);
void SumAverage( STU *head );
STU *InputNewRecord( STU *node);
STU *FindOneNode( STU *head ,char *name);
STU *FindNextNode( STU *head );
void Sort( STU *head );
STU *FindPreNode( STU *head );
main() /* 主程序 */
{
char c;
STU *head;
head = (STU *)malloc( sizeof(STU) ); /* 动态申请内存空间 */
head->next = NULL; /* 将指向下一个节点的指针赋空 */
firsthead = head; /* 记住第一个节点 */
while(1)
{
c = Menu(); /* 调用菜单函数 */
switch(c)
{
case '1' : List(head);
break;
case '2' : AppendNode(head);
break;
case '3' : DeleteNode(head);
break;
case '4' : ChangeNode(head);
break;
case '5' : SearchNode(head);
break;
case '6' : Sort(head);
break;
case '7' : Exit(head);
break;
default : break;
}
printf("\nPress anykey to main menu.");
getch();
}
}
/* 函数功能:获得节点个数子模块
函数参数:结构体指针head,表示指向链表第一个节点
函数返回值: 当前所有的节点个数
*/
int GetNodeNumber(STU *head) /* 获得节点个数子模块 */
{
STU *p;
int size = 1;
p = head->next;
while(p!=NULL) /* 访问每一个节点,计数器加1,直到链表结束 */
{
p = p->next;
size++;
}
return size;
}
/* 函数功能:菜单子模块,显示菜单功能并获得键盘选择
函数参数:无
函数返回值:输入的键盘ASCII码
*/
char Menu(void) /* 菜单显示模块 */
{
printf("\n 1. List record \n");
printf(" 2. Append record \n");
printf(" 3. Delete record \n");
printf(" 4. Change record \n");
printf(" 5. Search record \n");
printf(" 6. Sort record according to sum \n");
printf(" 7. Exit to DOS \n");
return getch();
}
/* 函数功能:列表模块,将所有的节点按照统一的格式输出
函数参数:结构体指针head,表示指向链表第一个节点
函数返回值:无
*/
void List(STU *head) /* 列表模块,将所有的节点按照统一的格式输出 */
{
STU *p;
int i;
p = head->next;
if (p == NULL)
{
printf("\nThe Record is empty!");
}
else
{
printf("\nStudent score as fellow:");
while(p!=NULL)
{
printf("\n%-4d%-10s",p->number,p->name);
for (i=0;i<NUMOFCOURSE;i++)
printf("%-5d",p->score[i]);
printf("%-10.2f%-6.2f",p->sum,p->average);
p = p->next;
}
}
}
/* 函数功能:在链表的末尾添加新的节点
函数参数:结构体指针head,表示指向链表第一个节点
函数返回值:无
*/
void AppendNode(STU *head) /* 添加节点模块 */
{
char c;
int size;
STU *p, *newnode,*last;
if (!OkOrNot("Append")) return;
last = head;
p = head->next;
while(p!=NULL) /*查找当前链表的最后一个节点*/
{
last = p;
p = p->next;
}
size = GetNodeNumber( head );
newnode = (STU*)malloc(sizeof(STU)); /* 动态申请新节点的内存 */
newnode->next = NULL; /*对节点中的成员分别赋值 */
p = InputNewRecord( newnode ); /*对节点中的成员赋值*/
newnode->number = size;
last->next = p;
}
/* 函数功能:通过键盘对新增加的节点内容进行赋值
函数参数:结构体指针node,表示指向链表的一个节点的指针
函数返回值:指向该节点的指针
*/
STU *InputNewRecord(STU *node) /* 对节点中的成员赋值子模块 */
{
int i;
printf("\nInput Number : ");
scanf("%d",node->number); /*输入学号*/
printf("\nInput Name : "); /*输入姓名*/
scanf("%s",node->name);
for(i=0;i<NUMOFCOURSE;i++)
{
printf("\nInput NO.%d score : ",i+1); /*输入各科成绩*/
scanf("%d",&node->score[i]);
}
SumAverage( node ); /*求一个学生的各科成绩的总和与平均值*/
return node;
}
/* 函数功能:删除某个节点
函数参数:结构体指针head,表示指向链表的第一个节点的指针
函数返回值:无
*/
void DeleteNode(STU *head) /* 删除某个节点 */
{
STU *nownode;
char name[20];
printf("\nInput the name that you want to delete:");
scanf("%s",name); /*输入要删除的节点的学生的名字*/
if (!OkOrNot("delete"))
return;
nownode = FindOneNode( head,name ); /* 找到要删除的节点 */
if (nownode != NULL && nownode == head )
{ /* 如果要删除的节点是链表的头一个*/
firsthead = nownode->next; /*节点必须将删掉头一个结点后的剩余*/
head->next = nownode->next; /*节点的头节点保留下来 */
}
/* 如果删除的是尾节点,尾节点 */
if (nownode != NULL && nownode->next == NULL)
FindPreNode( nownode )->next = NULL;/* 前一个节点的指针必须赋空值 */
else
FindPreNode( nownode )->next = nownode->next;
printf("\nThe record of %s has been delete",name);
if (nownode == NULL )
printf("\nCan`t find the record of %s",name);
}
/* 函数功能:修改节点中的内容子模块
函数参数:结构体指针head,表示指向链表的第一个节点的指针
函数返回值:无
*/
void ChangeNode(STU *head) / * 修改节点中的内容子模块 */
{
STU *nownode;
int i;
char name[20];
printf("\nInput the name of changing record:");
scanf("%s",name); /* 按姓名查找要修改的节点 */
if (!OkOrNot("change"))
return;
nownode = FindOneNode(head, name);
if (nownode != NULL )
{
printf("\n%-4d%-10s",nownode->number,nownode->name);
for (i=0;i<NUMOFCOURSE;i++)
printf("%-5d",nownode->score[i]);
printf("%-10.2f%-10.2f",nownode->sum,nownode->average);
InputNewRecord( nownode ); /* 重新输入结点内容 */
}
}
/* 函数功能:按成绩的总和的大小次序排列节点,采用交换法
函数参数:结构体指针head,表示指向链表的第一个节点的指针
函数返回值:无
*/
void Sort(STU *head ) /* 按成绩的总和的大小次序排列节点,采用交换法 */
{
STU *temp;
STU temp1;
int flag = 0,i;
for (;;)
{
flag = 0 ;
temp = head->next;
while (temp->next != NULL)
{
if (temp->sum < temp->next->sum )
{
/* 如果后一个节点的总成绩比前一个节点的总成绩高,则交换两个节点中的内
容。注意只交换内容,而节点的顺序不变,即节点中的next指针的内容不进
行交换。
*/
temp1.number = temp->number;
strcpy(temp1.name, temp->name);
for (i=0;i<NUMOFCOURSE;i++)
temp1.score[i] = temp->score[1];
temp1.sum = temp->sum;
temp1.average = temp->average;
temp->number = temp->next->number;
strcpy(temp->name, temp->next->name);
for (i=0; i<NUMOFCOURSE; i++)
temp->score[i] = temp->next->score[i];
temp->sum = temp->next->sum;
temp->average = temp->next->average;
temp->next->number = temp1.number;
strcpy(temp->next->name, temp1.name);
for (i=0;i<NUMOFCOURSE;i++)
temp->next->score[i] = temp1.score[i];
temp->next->sum = temp1.sum;
temp->next->average = temp1.average;
flag = 1;
}
temp = temp->next;
}
if (!flag ) break;
}
printf("\nSort success");
}
/* 函数功能:查找并显示模块,如果找到了,则显示该节点中的内容,否则显示"未找到"
函数参数:结构体指针head,表示指向链表的第一个节点的指针
函数返回值:无
*/
void SearchNode(STU *head) /* 按照学生姓名查找节点 */
{
int i;
STU *nownode;
char name[20],c;
printf("\nInput the name for searching:");
scanf("%s",name);
nownode = Fi