/*
2017年10月19日19:23:29
目的:自己去编写一个单链表并且对其进行打印、查找、插入、删除等
一些列操作。
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN sizeof(struct student_node)
#define Max_studnet 100 //学生数量最大值,可根据情况调节
typedef struct student_node
{
long num;
char name[20]; //姓名长度不超过20个字符
float score;
struct student_node *next;
} LinkList; //自定义链表
int main()
{
LinkList *LinkListCreat(); //创建链表,返回表头指针
void print(LinkList *P); //函数声明,打印学生信息
void sort(LinkList *p); //学生成绩排序函数
LinkList *LocatebyID(LinkList *p, long n); //按学号查找节点
LinkList *LocatebyNum(LinkList *p, int n); //按序号查找节点
LinkList *LocatebyVal(LinkList *p, char name[]); //按姓名查找学生
int Insert(LinkList *p, int n, long num1, char name1[], float score1); //在第n个位置插入学生信息,创建新节点
int Delete(LinkList *p, int n); //删除第n个学生的信息
char x;
long id; //学号
LinkList *p, *q, *t;
//插入信息所用到的变量
int n1; //插入学生信息位置
long num1;
char name1[20];
float score1;
//创建链表
p = LinkListCreat(); //创建链表,p指向表头节点
q = p->next; //q指向表头节点后的第一个节点,即序号为1的节点
printf("学生管理系统使用方法:n");
printf("功能 (p)t输出学生信息n");
printf("功能 (s)t对按分数的大小对学生进行排序n");
printf("功能 (l)t按学号查找学生信息n");
printf("功能 (i)t在某位置插入学生信息n");
printf("功能 (d)t删除某学生的信息n");
printf("功能 (q)t退出n");
while(1)
{
printf("请输入功能选项:t");
getchar(); //过滤回车符
scanf("%c", &x);
//过滤回车符,即如果输入了回车符,则继续提示用户输入
if(x == 'n')
{
continue;
}
switch(x)
{
//打印输出功能
//可以使用打印函数替换本部分程序
case 'p':
while(q) //q为序号1的节点
{
printf("%ldt%st%fn",q->num, q->name, q->score);
q = q->next; //q指向下一个节点
}
q = p->next; //命令执行完成后,指针指向原位置
break;
//对学生成绩进行排序并输出
case 's':
sort(q); //对学生成绩排序并且输出
q = p->next; //命令执行完成后,指针指向原位置
break;
//按学号查询学生信息
case 'l':
printf("请输入学生学号:");
scanf("%ld", &id);
t = LocatebyID(q, id);
q = p->next; //命令执行完成后,指针指向原位置
if(t == NULL)
{
printf("错误!没有这个学生n");
}
else
printf("%ldt%st%fn",t->num, t->name, t->score);
break;
//在指定位置插入学生信息
case 'i':
printf("请输入插入位置:t");
scanf("%d", &n1);
printf("请输入学号、姓名、分数:n");
printf("学号:t");
scanf("%ld", &num1);
printf("姓名:t");
getchar();
gets(name1);
printf("成绩:t");
scanf("%f", &score1);
//调用插入学生信息函数
Insert(q, n1, num1, name1, score1);
q = p->next; //命令执行完成后指针指向原来位置
printf("插入该学生信息后打印学生信息:n");
print(q);
q = p->next; //命令执行完成后指针指向原来位置
break;
case 'd':
printf("请输入需要删除的学生序号:");
scanf("%d", &n1);
Delete(q, n1);
q = p->next; //命令执行完成后指针指向原位置
printf("删除操作后打印学生信息:n");
print(q);
q = p->next; //命令执行完成后指针指向原位置
break;
case 'q':
return 0;
break;
default:
printf("功能输入错误!n");
break;
}
}
return 0;
}
LinkList *LinkListCreat()
{
LinkList *p, *p1, *p2;
long num1;
char name1[20];
float score1;
//创建表头节点
p = (LinkList *)malloc(LEN);
//赋初始值
p->num = 0;
p->name[20] = "nothing";
p->score = 0;
p->next = NULL;
p1 = p; //p1指向表头节点
printf("请输入学生学号、姓名、分数:n");
printf("注意:学号为0代表输入结束n");
printf("学号:t");
scanf("%ld", &num1);
printf("姓名:t");
getchar(); //过滤回车符
gets(name1);
printf("成绩:t");
scanf("%f", &score1);
for( ; num1 != 0; ) //学号为0则结束
{
p2 = (LinkList *)malloc(LEN);
p2->num = num1;
strcpy(p2->name, name1);
p2->score = score1;
p2->next = NULL;
p1->next = p2;
p1 = p2;
printf("学号:t");
scanf("%ld", &num1);
if(num1 != 0)
{
printf("姓名:t");
getchar();
gets(name1);
printf("成绩:t");
scanf("%f", &score1);
}
}
return p;
}
//打印指针,记得执行完成后要将指针指向原位置即序号1元素
void print(LinkList *p)
{
while(p)
{
printf("%ldt%st%fn",p->num, p->name, p->score);
p = p->next;
}
}
//排序函数定义
//选择排序法,成绩从高到低排序
void sort(LinkList *p)
{
int i, j, sum = 0; //sum 用来保存学生个数
float temp;
LinkList *q;
float array[Max_studnet];
int k;
//统计学生个数
q = p; //保护现场,保证不改变p的指向
while(q != NULL)
{
sum ;
q = q->next;
}
//将学生成绩放入数组
q = p; //q再次指向序号1节点
for(i = 0; i < sum; i )
{
array[i] = q->score; //将学生成绩放入数组
q = q->next;
}
//对学生成绩进行排序
for(i = 0; i < sum - 1; i )
{
k = i;
for(j = i 1; j < sum; j )
{
if(array[k] < array[j])
{
k = j;
}
}
if(k != i)
{
temp = array[k];
array[k] = array[i];
array[i] = temp;
}
}
//按顺序输出学生成绩
for(i = 0; i < sum; i )
{
printf("%ft", array[i]);
if( (i 1) % 5 == 0 )
printf("n");
}
printf("n");
}
//通过学号查询学生信息
LinkList *LocatebyID(LinkList *p, long n)
{
LinkList *q;
q = p;
while(q)
{
if(n == q->num)
{
return q;
}
q = q->next;
}
return NULL;
}
//定义按序号查找节点函数
LinkList *LocatebyNum(LinkList *p, int n)
{
int i = 1;
LinkList *q;
q = p;
while(q)
{
if(n == i)
{
return q;
}
i ;
q = q->next;
}
return NULL;
}
//定义插入函数
int Insert(LinkList *p, int n, long num1, char name1[], float score1)
{
LinkList *p1, *p2;
p1 = LocatebyNum(p, n - 1);
if(p1 == NULL)
{
printf("错误!不存在此节点!n");
return -1;
}
p2 = (LinkList *)malloc(LEN);
p2->num = num1;
strcpy(p2->name, name1);
p2->score = score1;
p2->next = p1->next;
p1->next = p2;
return 0;
}
//定义删除函数
int Delete(LinkList *p, int n)
{
LinkList *p1, *p2;
p1 = LocatebyNum(p, n - 1);
if(p1 == NULL)
{
printf("错误!不存在此节点!n");
return -1;
}
p2 = p1->next;
p1->next = p2->next;
free(p2);
return 0;
}
/*
在Code::Blocks中的输出结果为:
请输入学生学号、姓名、分数:
注意:学号为0代表输入结束
学号: 609
姓名: han
成绩: 86
学号: 611
姓名: xie
成绩: 58
学号: 0
学生管理系统使用方法:
功能 (p) 输出学生信息
功能 (s) 对按分数的大小对学生进行排序
功能 (l) 按学号查找学生信息
功能 (i) 在某位置插入学生信息
功能 (d) 删除某学生的信息
功能 (q) 退出
请输入功能选项: p
609 han 86.000000
611 xie 58.000000
请输入功能选项: s
86.000000 58.000000
请输入功能选项: l
请输入学生学号:609
609 han 86.000000
请输入功能选项: i
请输入插入位置: 2
请输入学号、姓名、分数:
学号: 610
姓名: li
成绩: 98
插入该学生信息后打印学生信息:
609 han 86.000000
610 li 98.000000
611 xie 58.000000
请输入功能选项: d
请输入需要删除的学生序号:3
删除操作后打印学生信息:
609 han 86.000000
610 li 98.000000
请输入功能选项: q
Process returned 0 (0x0) execution time : 77.873 s
Press any key to continue.
2017年10月20日20:02:01
心得:功夫不负有心人,终于独立编写出了一个像样的程序,基本满足了自己的想法。
但问题仍然十分突出,例如错误的输入会导致莫名其妙的结果,这是本程序的bug,到此
仅仅是一个开始,而非一个结束,继续学习新的内容,复习旧的内容,并时常编写一些
有想法的程序去检验自己的学习成果。加油。
*/